2015-09-25 73 views
0

我正在使用Grails和AngularJS一个RESTful的Twitter/Facebook的克隆,所以这是一个标准的用户可以发布,用户可以像帖子和用户可以关注其他用户。错误errors.GrailsExceptionResolver - JSONException错位endArray

我正在使用JSON对象编组器,因此将在JSON中呈现域类的hasManybelongsTo的属性。

我插入了UserPost域之间建立必要的关系对类似的功能,当我在Bootstrap.groovy实现他们,如果我发送GET请求api/posts/一切工作正常,但问题是,当我使用实现它们按钮。 此按钮发送PUT请求api/posts/:id和这个去我PostControllerupdate()方法。等被插入到数据库,但如果我再传送GET请求api/posts我得到这个错误

....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 

这是我的代码

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") as 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] as JSON) 
     } 
    } 

    def show(){ 
     def post = Post.get(params.id) 
     render post as 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] as 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 am 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") as 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] as JSON) 
     } 
    } 

    def show(){ 
     def post = Post.get(params.id) 
     render post as 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] as JSON) 
     } 
    } 
} 

我试图消除JSON对象marshallers,并没有再给出错误,但我将无法访问属性hasMany。所以我猜主要的问题是JSON对象marshallers。我是否错误地执行它们?或者有使用JSON对象编组的替代方法吗?但又一次它工作得很好,因为我实现它们在Bootstrap.groovy 另外,我试图改变post.save(flush:true)只是post.save()它并没有给出来的错误,但类似不被保存在数据库中。


以防万一您对JSON的渲染感兴趣。 这是一个GET请求api/posts/

没有JSON对象marshallers

[ 
    { 
    "class": "com.patrickjuen.restsocnet.Post", 
    "id": 4, 
    "content": "i am 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 
    } 
    } 
] 

使用JSON对象marshallers

[ 
    { 
    "id": 4, 
    "content": "i am 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 am 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 am 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 am 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 am user2 guys hehehe", 
        "dateCreated": "2015-09-25T17:50:58Z", 
        "user": { 
         "_ref": "../../../..", 
         "class": "com.patrickjuen.restsocnet.User" 
        }, 
        "likers": [] 
        } 
       ] 
       } 
      ] 
      }, 
      { 
      "_ref": "../../../../..", 
      "class": "com.patrickjuen.restsocnet.Post" 
      } 
     ] 
     } 
    ] 
    } 
] 
+0

对此有何更新的评论之一插入?我还没有发现任何工作。我尝试过使用GSON并使用深度。我认为这可能与级联有关,但我不确定。 – uLan

回答