json - ERROR errors.GrailsExceptionResolver - JSONException Misplaced endArray -


i making restful twitter/facebook clone using grails , angularjs, it's standard user can post, user can posts , user can follow other users.

i using json object marshallers attributes of hasmany or belongsto of domain class rendered in json.

i have inserted necessary relationships between user , post domain feature , when implement them in bootstrap.groovy , if send get request api/posts/ works fine problem when implement them using button. button sends put request api/posts/:id , goes update() method of postcontroller. being inserted database if send again get request api/posts error

....error | 2015-09-26 00:54:35,986 [http-bio-8090-exec-9] error  errors.grailsexceptionresolver   - jsonexception occurred when processing request: [get] /restsocnet/api/posts misplaced endarray.. stacktrace follows: message: misplaced endarray.     line | method ->>  202 | value              in grails.converters.json - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    162 | convertanother     in     '' |    202 | value . . . . . .  in     '' |    134 | render             in     '' |    150 | render . . . . . . in     '' |     19 | index              in com.patrickjuen.restsocnet.postcontroller |    198 | dofilter . . . . . in grails.plugin.cache.web.filter.pagefragmentcachingfilter |     63 | dofilter           in grails.plugin.cache.web.filter.abstractfilter |    118 | processfilterchain in grails.plugin.springsecurity.rest.resttokenvalidationfilter |     84 | dofilter           in     '' |     53 | dofilter . . . . . in grails.plugin.springsecurity.web.filter.grailsanonymousauthenticationfilter |    143 | dofilter           in grails.plugin.springsecurity.rest.restauthenticationfilter |     62 | dofilter . . . . . in grails.plugin.springsecurity.web.authentication.logout.mutablelogoutfilter |     82 | dofilter           in com.brandseye.cors.corsfilter |   1142 | runworker . . . .  in java.util.concurrent.threadpoolexecutor |    617 | run                in java.util.concurrent.threadpoolexecutor$worker ^    745 | run . . . . . . .  in java.lang.thread 

these codes

user.groovy

package com.patrickjuen.restsocnet  class user implements serializable {      private static final long serialversionuid = 1      transient springsecurityservice      string username     string password     boolean enabled = true     boolean accountexpired     boolean accountlocked     boolean passwordexpired     static hasmany = [posts: post, likedpost: post]     static mappedby = [posts: "user"]       user(string username, string password) {         this()         this.username = username         this.password = password     }      @override     int hashcode() {         username?.hashcode() ?: 0     }      @override     boolean equals(other) {         is(other) || (other instanceof user && other.username == username)     }      @override     string tostring() {         username     }      set<role> getauthorities() {         userrole.findallbyuser(this)*.role     }      def beforeinsert() {         encodepassword()     }      def beforeupdate() {         if (isdirty('password')) {             encodepassword()         }     }      protected void encodepassword() {         password = springsecurityservice?.passwordencoder ? springsecurityservice.encodepassword(password) : password     }      static transients = ['springsecurityservice']      static constraints = {         username blank: false, unique: true         password blank: false         likedpost nullable: true     }      static mapping = {         password column: '`password`'         posts lazy: false, sort: 'datecreated', order: 'desc'         likedpost lazy: false      } }    package com.patrickjuen.restsocnet  import grails.converters.json  //import grails.plugin.springsecurity.annotation.secured import org.springframework.security.access.annotation.secured   @secured(['isfullyauthenticated()']) class postcontroller {      static allowedmethods = [save: "post", update: "put", delete: "delete"]       def springsecurityservice      def index() {         render post.list(sort: "datecreated", order: "desc") json     }      def save(){         def newpost = new post(request.json)         if(!newpost.haserrors()){             def currentuser = user.get(springsecurityservice.principal.id)             println currentuser             newpost.user = currentuser             newpost.save(failonerror: true)  //            currentuser.addtoposts(newpost)             render (['success': true] json)         }     }      def show(){         def post = post.get(params.id)         render post json     }      def update(){         def post = post.findbyid(params.id)         if(!post.haserrors()){             def currentuser = user.get(springsecurityservice.principal.id)             post.addtolikers(currentuser)             post.save(flush: true)             render(['success': true] json)         }     } } 

post.groovy

package com.patrickjuen.restsocnet  class post {      string content     date datecreated     user user     static belongsto = user     static hasmany = [likers: user] //    static mappedby = [likers: "likedpost"]     static constraints = {         likers nullable: true     }     static mapping = {         likers lazy: false     } } 

bootstrap.groovy

import com.patrickjuen.restsocnet.post import com.patrickjuen.restsocnet.role import com.patrickjuen.restsocnet.user import com.patrickjuen.restsocnet.userrole import grails.converters.json  class bootstrap {      def init = { servletcontext ->          json.registerobjectmarshaller(user) {             def returnarray = [:]             returnarray['id'] = it.id             returnarray['username'] = it.username             returnarray['posts'] = it.posts             return returnarray         }         json.registerobjectmarshaller(post) {             def returnarray = [:]             returnarray['id'] = it.id             returnarray['content'] = it.content             returnarray['datecreated'] = it.datecreated             returnarray['user'] = it.user             returnarray['likers'] = it.likers             return returnarray         }           def role = new role(authority: "role_user")         def user1 = new user(username: "user1", password: "password")         def user2 = new user(username: "user2", password: "password")         role.save()         user1.save()         user2.save()          def post1 = new post(content: "new post number 1")         def post2 = new post(content: "new post number 2")         def post3 = new post(content: "one more ")         def post4 = new post(content: "i user2 guys hehehe")         post1.save()         post2.save()         post3.save()         post4.save()          user1.addtoposts(post1)         user1.addtoposts(post2)         user1.addtoposts(post3)         user2.addtoposts(post4)         post2.addtolikers(user2)         post2.addtolikers(user1)         post1.addtolikers(user1)          userrole.create(user1, role, true)         userrole.create(user2, role, true)     }     def destroy = {     } } 

postcontroller.groovy

package com.patrickjuen.restsocnet  import grails.converters.json  //import grails.plugin.springsecurity.annotation.secured import org.springframework.security.access.annotation.secured   @secured(['isfullyauthenticated()']) class postcontroller {      static allowedmethods = [save: "post", update: "put", delete: "delete"]       def springsecurityservice      def index() {         render post.list(sort: "datecreated", order: "desc") json     }      def save(){         def newpost = new post(request.json)         if(!newpost.haserrors()){             def currentuser = user.get(springsecurityservice.principal.id)             println currentuser             newpost.user = currentuser             newpost.save(failonerror: true)  //            currentuser.addtoposts(newpost)             render (['success': true] json)         }     }      def show(){         def post = post.get(params.id)         render post json     }      def update(){         def post = post.findbyid(params.id)         if(!post.haserrors()){             def currentuser = user.get(springsecurityservice.principal.id)             post.addtolikers(currentuser)             post.save(flush: true)             render(['success': true] json)         }     } } 

i tried removing json object marshallers , doesn't give out error anymore won't able access attributes of hasmany. guess main problem json object marshallers. implementing them wrongly? or there alternative using json object marshallers? yet again works fine implement them in bootstrap.groovy also, tried changing post.save(flush:true) post.save() doesn't give out error not being saved in database.


just in case interested in json being rendered. get request api/posts/

without json object marshallers

[   {     "class": "com.patrickjuen.restsocnet.post",     "id": 4,     "content": "i user2 guys hehehe",     "datecreated": "2015-09-25t17:39:10z",     "likers": [],     "user": {       "class": "com.patrickjuen.restsocnet.user",       "id": 2     }   },   {     "class": "com.patrickjuen.restsocnet.post",     "id": 3,     "content": "one more",     "datecreated": "2015-09-25t17:39:10z",     "likers": [],     "user": {       "class": "com.patrickjuen.restsocnet.user",       "id": 1     }   },   {     "class": "com.patrickjuen.restsocnet.post",     "id": 2,     "content": "new post number 2",     "datecreated": "2015-09-25t17:39:10z",     "likers": [       {         "class": "com.patrickjuen.restsocnet.user",         "id": 1       },       {         "class": "com.patrickjuen.restsocnet.user",         "id": 2       }     ],     "user": {       "class": "com.patrickjuen.restsocnet.user",       "id": 1     }   },   {     "class": "com.patrickjuen.restsocnet.post",     "id": 1,     "content": "new post number 1",     "datecreated": "2015-09-25t17:39:10z",     "likers": [       {         "class": "com.patrickjuen.restsocnet.user",         "id": 1       }     ],     "user": {       "class": "com.patrickjuen.restsocnet.user",       "id": 1     }   } ] 

with json object marshallers

[   {     "id": 4,     "content": "i user2 guys hehehe",     "datecreated": "2015-09-25t17:50:58z",     "user": {       "id": 2,       "username": "user2",       "posts": [         {           "_ref": "../../../..",           "class": "com.patrickjuen.restsocnet.post"         }       ]     },     "likers": []   },   {     "id": 3,     "content": "one more",     "datecreated": "2015-09-25t17:50:58z",     "user": {       "id": 1,       "username": "user1",       "posts": [         {           "_ref": "../../../..",           "class": "com.patrickjuen.restsocnet.post"         },         {           "id": 2,           "content": "new post number 2",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": [             {               "_ref": "../../../../..",               "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"             },             {               "id": 2,               "username": "user2",               "posts": [                 {                   "id": 4,                   "content": "i user2 guys hehehe",                   "datecreated": "2015-09-25t17:50:58z",                   "user": {                     "_ref": "../../../..",                     "class": "com.patrickjuen.restsocnet.user"                   },                   "likers": []                 }               ]             }           ]         },         {           "id": 1,           "content": "new post number 1",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": [             {               "_ref": "../../../../..",               "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"             }           ]         }       ]     },     "likers": []   },   {     "id": 2,     "content": "new post number 2",     "datecreated": "2015-09-25t17:50:58z",     "user": {       "id": 1,       "username": "user1",       "posts": [         {           "id": 3,           "content": "one more",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": []         },         {           "_ref": "../../../..",           "class": "com.patrickjuen.restsocnet.post"         },         {           "id": 1,           "content": "new post number 1",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": [             {               "_ref": "../../../../..",               "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"             }           ]         }       ]     },     "likers": [       {         "id": 1,         "username": "user1",         "posts": [           {             "id": 3,             "content": "one more",             "datecreated": "2015-09-25t17:50:58z",             "user": {               "_ref": "../../../..",               "class": "com.patrickjuen.restsocnet.user"             },             "likers": []           },           {             "_ref": "../../../../..",             "class": "com.patrickjuen.restsocnet.post"           },           {             "id": 1,             "content": "new post number 1",             "datecreated": "2015-09-25t17:50:58z",             "user": {               "_ref": "../../../..",               "class": "com.patrickjuen.restsocnet.user"             },             "likers": [               {                 "_ref": "../../../../..",                 "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"               }             ]           }         ]       },       {         "id": 2,         "username": "user2",         "posts": [           {             "id": 4,             "content": "i user2 guys hehehe",             "datecreated": "2015-09-25t17:50:58z",             "user": {               "_ref": "../../../..",               "class": "com.patrickjuen.restsocnet.user"             },             "likers": []           }         ]       }     ]   },   {     "id": 1,     "content": "new post number 1",     "datecreated": "2015-09-25t17:50:58z",     "user": {       "id": 1,       "username": "user1",       "posts": [         {           "id": 3,           "content": "one more",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": []         },         {           "id": 2,           "content": "new post number 2",           "datecreated": "2015-09-25t17:50:58z",           "user": {             "_ref": "../../../..",             "class": "com.patrickjuen.restsocnet.user"           },           "likers": [             {               "_ref": "../../../../..",               "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"             },             {               "id": 2,               "username": "user2",               "posts": [                 {                   "id": 4,                   "content": "i user2 guys hehehe",                   "datecreated": "2015-09-25t17:50:58z",                   "user": {                     "_ref": "../../../..",                     "class": "com.patrickjuen.restsocnet.user"                   },                   "likers": []                 }               ]             }           ]         },         {           "_ref": "../../../..",           "class": "com.patrickjuen.restsocnet.post"         }       ]     },     "likers": [       {         "id": 1,         "username": "user1",         "posts": [           {             "id": 3,             "content": "one more",             "datecreated": "2015-09-25t17:50:58z",             "user": {               "_ref": "../../../..",               "class": "com.patrickjuen.restsocnet.user"             },             "likers": []           },           {             "id": 2,             "content": "new post number 2",             "datecreated": "2015-09-25t17:50:58z",             "user": {               "_ref": "../../../..",               "class": "com.patrickjuen.restsocnet.user"             },             "likers": [               {                 "_ref": "../../../../..",                 "class": "com.patrickjuen.restsocnet.user_$$_javassist_5"               },               {                 "id": 2,                 "username": "user2",                 "posts": [                   {                     "id": 4,                     "content": "i user2 guys hehehe",                     "datecreated": "2015-09-25t17:50:58z",                     "user": {                       "_ref": "../../../..",                       "class": "com.patrickjuen.restsocnet.user"                     },                     "likers": []                   }                 ]               }             ]           },           {             "_ref": "../../../../..",             "class": "com.patrickjuen.restsocnet.post"           }         ]       }     ]   } ] 

i found solution. code needs inserted in config.groovy

grails.converters.json.circular.reference.behaviour = "insert_null"

i saw in 1 of comments in article http://manbuildswebsite.com/2010/02/15/rendering-json-in-grails-part-3-customise-your-json-with-object-marshallers/


Comments