将JSON绑定到嵌套的Grails域对象

将JSON绑定到嵌套的Grails域对象,json,data-binding,grails,gorm,Json,Data Binding,Grails,Gorm,我正在开发一个RESTful接口,用于为JavaScript应用程序提供JSON数据 在服务器端,我使用Grails1.3.7并使用GORM域对象进行持久化。我实现了一个自定义JSON封送器来支持封送嵌套的域对象 以下是示例域对象: class SampleDomain { static mapping = { nest2 cascade: 'all' } String someString SampleDomainNested nest2 } 及 SampleDoma

我正在开发一个RESTful接口,用于为JavaScript应用程序提供JSON数据

在服务器端,我使用Grails1.3.7并使用GORM域对象进行持久化。我实现了一个自定义JSON封送器来支持封送嵌套的域对象

以下是示例域对象:

class SampleDomain {
    static mapping = { nest2 cascade: 'all' }
    String someString
    SampleDomainNested nest2
}

SampleDomain资源在URL/rs/sample/so/rs/sample/1下发布,指向ID为1的SampleDomain对象

当我使用自定义json封送器(GET on/rs/sample/1)呈现资源时,我得到以下数据:

{
    "someString" : "somevalue1",
    "nest2" : {
        "someField" : "someothervalue"
    }
}
这正是我想要的

现在问题来了:我试图通过PUT将相同的数据发送到resource/rs/sample/1

要将json数据绑定到域对象,处理请求的控制器将调用
def Domain=SampleDomain.get(id)
Domain.properties=data
,其中数据是未经签名的对象

“someString”字段的绑定工作正常,但嵌套对象没有使用嵌套数据填充,因此我得到一个错误,即属性“nest2”为null,这是不允许的

我已经尝试实现一个自定义的
属性编辑器支持
以及
结构属性编辑器
,并为类注册编辑器

奇怪的是,只有在我提供非嵌套值时才会调用编辑器。因此,当我通过PUT将以下内容发送到服务器时(这没有任何意义;)

至少调用了属性编辑器

我查看了
GrailsDataBinder
的代码。我发现,通过指定关联的路径而不是提供映射来设置关联的属性似乎是有效的,因此以下方法也同样有效:

{
    "someString" : "somevalue1",
    "nest2.somefield" : "someothervalue"
}
但这对我没有帮助,因为我不想实现自定义JavaScript到JSON对象序列化程序

是否可以使用嵌套映射使用Grails数据绑定?或者我真的需要为每个域类手工实现吗

非常感谢


Martin

它要求您提供以下类名:

{ class:"SampleDomain", someString: "abc", 
nest2: { class: "SampleDomainNested", someField:"def" }
} 
我知道,它需要不同的输入和输出


正如我在前面的评论中提到的,您最好使用gson库。

不知道为什么要编写自己的json封送器,并使用xstream

对于后端(基于grails的)服务,我们对xstream非常满意,通过这种方式,您可以用xml或json呈现marshall,或者覆盖特定对象的默认封送

抛弃似乎产生了一个更紧凑、更不容易被人阅读的JSON,您可以遇到一些库冲突的东西,但是默认的内部JSON流呈现器是不错的


如果要向公众发布该服务,则需要花时间返回相应的HTTP协议错误响应等。。。($.02)

由于这个问题被多次投票,我想分享一下我最后做了什么:

因为我还有一些需要实现的需求,比如安全性等,所以我实现了一个服务层,它对控制器隐藏域对象。我引入了一个“动态DTO层”,它将域对象转换为Groovy映射,可以使用标准序列化程序轻松序列化,并手动实现更新。所有的半自动/元编程/命令模式/。。。我尝试实现的基于数据库的解决方案在某些时候失败了,主要导致奇怪的GORM错误或大量配置代码(以及大量挫折)。DTO的更新和序列化方法相当简单,可以非常快速地实现。它也不会引入大量重复代码,因为如果不想发布内部域对象结构,则必须指定如何序列化域对象。也许这不是最优雅的解决方案,但它是唯一真正对我有效的解决方案。它还允许我实现批量更新,因为更新逻辑不再连接到http请求

然而,我必须说,我不认为grails是最适合这种应用程序的技术堆栈,因为它使您的应用程序非常重,而且不稳定。我的经验是,一旦你开始做框架默认不支持的事情,它就会变得一团糟。此外,我不喜欢grails中的“repository”层实际上只作为域对象的一部分存在,这会带来很多问题,并导致几个“代理服务”模拟存储库层。如果您开始使用json rest接口构建应用程序,我建议您要么使用非常轻量级的技术,如node.js,要么使用标准的spring framework+spring mvc+spring数据和漂亮干净的dto层(这就是我迁移到的技术,它的工作非常有魅力)。你不必写很多样板代码,你完全可以控制实际发生的事情。此外,您还可以获得强大的类型,这将提高开发人员的生产率和可维护性,并使额外的LOC合法化。当然,强大的打字意味着强大的工具

我开始写一篇博客,描述我提出的架构(当然是一个示例项目),但是我现在没有太多时间来完成它。完成后,我将在这里链接到它以供参考

希望这能对经历类似问题的人起到启发作用


干杯

你也有自定义json解组器吗?没有,我没有自定义json解组器。我使用request.JSON解析请求。我想要的是一个属性编辑器,它既支持从映射创建域对象,也支持按ID加载/映射域对象。您尝试过这个插件吗:谢谢您的帮助
{
    "someString" : "somevalue1",
    "nest2.somefield" : "someothervalue"
}
{ class:"SampleDomain", someString: "abc", 
nest2: { class: "SampleDomainNested", someField:"def" }
}