我想在Grails中實現一個自定義編組器。這裏的編組:無法獲得Grails ObjectMarshaller的實現<JSON>工作
class AdultPlanningMarshaller implements ObjectMarshaller<JSON> {
boolean supports(Object theObject)
{
return theObject instanceof AdultPlanning
}
void marshalObject(Object theObject, JSON theConverter)
{
AdultPlanning adult = (AdultPlanning)theObject
JSONWriter writer = theConverter.getWriter()
writer.object()
writer.key('id').value(adult.id)
...
writer.endObject()
}
}
我對其進行註冊BootStrap.groovy中,當我運行我的集成測試,正確的方法支持火災和marshalObject方法被調用合適的對象和JSON對象。
當我打的:
writer.object()
電話,一個異常被拋出:
org.codehaus.groovy.grails.web.json.JSONException: Misplaced object: expected mode of INIT, OBJECT or ARRAY but was DONE
所以它看起來像筆者已經做了什麼事完成,但是我不知道是什麼。
JSON編組沒有太多的文檔,實例很薄弱,但我認爲我已經做到了這一點,但肯定無法正常工作。任何提示將不勝感激。
調試器的進一步工作似乎表明,對象編組器正在被調用兩次,儘管斷點僅在第二次調用中出於某種原因。第一次通過它似乎工作得很好,因爲當斷點確實工作時,我通過Converter.getWriter()獲得的JSONWriter正確地編組了對象的JSON。這是第二次調用,因爲對象已經被編組,並且JSONWriter不再處於「init」狀態。沒有什麼明顯可用來分辨這兩個電話之間的區別,但爲什麼這個編組被稱爲兩次?
按照要求,這裏是控制器。這是一個的被觸發show動作:觸發它
class PrimaryController extends RestfulController implements AlwaysRenderJsonException {
def springSecurityService
def familyService
static responseFormats = ['json']
PrimaryController() {
/*
* Tell the base class the name of the resource under management.
*/
super(Primary)
}
@Override
protected Primary createResource() {
//def instance = super.createResource()
//TODO: Should be able to run the above line but there is an issue GRAILS-10411 that prevents it.
// Code from parent is below, as soon as the jira is fixed, remove the following lines:
Primary instance = resource.newInstance()
bindData instance, this.getObjectToBind()
//Code from super ends here
def family = familyService.safeGetFamily(params.long('familyId'))
familyService.addAdultToFamily(instance, family) // Add the primary member to the family.
return instance
}
/**
* Deletes a resource for the given id
* @param id The id
*/
@Override
def delete() {
if(handleReadOnly()) {
return
}
Child instance = queryForResource(params.id)
if (instance == null) {
notFound()
return
}
/*
* Because of the multiple belongsTo relationships of events, you have to get rid of all
* the events and make the profiles consistent BEFORE deleting the person instance.
*/
instance.removePerson()
request.withFormat {
'*'{ render status: NO_CONTENT } // NO CONTENT STATUS CODE
}
}
@Override
protected List<Primary> listAllResources(Map params) {
if (params.familyId == null)
{
throw new ESPException("params.familyId may not be null")
}
def user = springSecurityService.loadCurrentUser()
return \
AdultPlanning.where {
family.id == params.familyId \
&& family.user == user \
&& typeOfPerson == PeopleTypeEnum.PRIMARY
}.list()
}
@Override
protected Primary queryForResource(Serializable id) {
def inst = familyService.safeGetAdult(Long.parseLong(id), params.long('familyId'))
/*
* It was safe to access the requested id, but the requested id may NOT be a primary
* so we need to check.
*/
return (inst instanceof Primary ? inst : null)
}
/**
* Show the primary for the specified family.
*
* @return
*/
@Override
def show() {
Primary primary = familyService.safeGetFamily(params.long('familyId'))?.primary
respond primary
}
}
和集成測試:
void "We should be able to show a primary."() {
given:
family.addToAdults(new Primary(firstName: "Barney"))
family.save()
family.adults.each { it.save() }
when:
controller.response.reset()
resetParameters(controller.params, [familyId: family.id])
controller.request.method = 'GET'
controller.show()
then:
1 * mSpringSecurityService.loadCurrentUser() >> user
controller.response.json
controller.response.json.firstName == "Barney"
}
這應該可行,您正在使用哪個grails版本?你可以發佈控制器操作代碼,你正在響應實例。 –
使用Grails 2.4.4 – user1416192