我试图在Grails中实现自定义marshaller。这是编组人员:
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中注册它,当我运行集成测试时,supports方法正确触发,并使用正确的对象和JSON对象调用marshalObject方法。
当我点击:
writer.object()
调用,抛出异常:
org.codehaus.groovy.grails.web.json.JSONException: Misplaced object: expected mode of INIT, OBJECT or ARRAY but was DONE
所以看起来作家已经完成了一些事情,但我不知道是什么。
关于JSON marshallers并没有很多关于JSON marshallers的文档,但是我认为我已经做到了这一点,但它确实无法正常工作。任何提示都将不胜感激。
使用调试器的进一步工作似乎表明对象编组器被调用了两次,尽管出于某种原因断点仅发生在第二次调用上。第一次通过它似乎工作正常,因为我通过theConverter.getWriter()得到的JSONWriter断点DOES工作时正确编组了对象的JSON。这是第二次调用,因为对象已被编组并且JSONWriter不再位于&#34; init&#34;州。现在没有什么可以说出这两个电话之间的区别,但是为什么要把两个电话调用两次?
根据要求,这是控制器。它是被触发的节目动作:
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"
}
答案 0 :(得分:2)
嗯,这很令人尴尬。
我使用IntelliJ作为我的Java / Groovy IDE。我今天早上做了一件与工作有关的事情并退出了IntelliJ。当我重新启动IntelliJ时,上面描述的完全可重现的问题不再发生,并且在所有情况下都会生成相应的JSON。
所以似乎IntelliJ状态以某种方式被破坏并且重新启动将其清除。
问题解决了。
我想。
感谢您的帮助/建议。
答案 1 :(得分:1)
正如OP所提到的,由于IntelliJ:
,可以触发此错误 org.codehaus.groovy.grails.web.json.JSONException: Misplaced object: expected mode of INIT, OBJECT or ARRAY but was DONE
实际上,在调试marshaller(例如)时,IntelliJ会显示&#34; toString()&#34;变量的变量,导致模式从INIT
变为DONE
。
您可能希望在遇到此问题时删除断点;)
答案 2 :(得分:0)
这样做的唯一原因可能是你已经为某些嵌套对象或数组响应启动了writer.object()
但是错过了写writer.endObject()
或者你已经写了两次。
因此请仔细检查所有写入对象的自定义编组器。
希望这有帮助!
谢谢,
SA