2011-09-23 63 views
39

我正在开发一个用于为JavaScript应用程序提供JSON数据的RESTful接口。将JSON绑定到嵌套的Grails域对象

在服务器端,我使用Grails 1.3.7并使用GORM域对象进行持久化。我实现了一个自定义的JSON的Marshaller支持编组嵌套的域对象

下面是样本域对象:

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

class SampleDomainNested { 
    String someField 
} 

的SampleDomain资源的URL/RS /样品下发布/ 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,这是不允许的。

我已经尝试过实现自定义PropertyEditorSupport以及StructuredPropertyEditor并注册该类的编辑器。

奇怪的是,编辑器只在我提供非嵌套值时被调用。所以,当我把下面通过把服务器(其中没有任何意义;))

{ 
    "someString" : "somevalue1", 
    "nest2" : "test" 
} 

至少属性编辑器被调用。我看了GrailsDataBinder的代码。我发现,设置的关联性似乎通过指定的关联路径,而不是提供地图,所以下面的工作以及工作:

{ 
    "someString" : "somevalue1", 
    "nest2.somefield" : "someothervalue" 
} 

,但这并不能帮助我,因为我不您想要实现一个自定义JavaScript到JSON对象序列化器。

是否可以使用嵌套地图使用Grails数据绑定?或者我真的很想为每个领域类手动实现?

非常感谢,

马丁

+0

你有一个自定义的json unmarshaller吗? – fixitagain

+0

不,我没有自定义json unmarshaller。我通过使用request.JSON解析请求。我想要的是一个属性编辑器,它既支持从Map​​创建域对象,也支持通过ID加载/映射域对象。 – frow

+1

你试过这个插件:http://www.grails.org/plugin/json-rest-api –

回答

1

它要求你提供德班名:

{ class:"SampleDomain", someString: "abc", 
nest2: { class: "SampleDomainNested", someField:"def" } 
} 

我知道,它需要不同的输入,输出它产生。

正如我在评论前面提到的,你可能会更好使用GSON库。

1

不知道为什么你写你自己的JSON编组,使用XStream左右。

http://x-stream.github.io/json-tutorial.html

我们一直很高兴使用XStream用于后端(基于Grails的)服务,这样你就可以在XML或JSON渲染马歇尔,或覆盖默认编组为一个特定的对象,如果你喜欢。

抛弃似乎产生了更紧凑较少人类可读的JSON,你可以碰到一些库冲突的东西,但默认的内部JSON流渲染器是体面的。

如果你打算将服务发布给公众,你会想花时间来恢复错误等相应的HTTP协议的响应...($ 0.02)

7

由于这个问题得到了upvoted几个有时我想和大家分享我到底做了:

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

但是我必须说,我不认为Grails是最适合这种应用的合适技术堆栈,因为它使你的应用是非常重的重量和inflexbile。我的经验是,一旦你开始做默认情况下不被框架支持的事情,它开始变得混乱。此外,我不喜欢这样一个事实,即grails中的“存储库”层实际上只是作为域对象的一部分存在,这引发了很多问题,并导致了几个模拟存储库层的“代理服务”。如果你开始用json rest接口构建一个应用程序,我会建议你选择一个非常轻量级的技术,比如node.js,或者如果你想/必须坚持一个基于java的堆栈,可以使用标准的spring framework +春天mvc +春天的数据与一个漂亮干净的dto层(这是我已经迁移到,它的作品就像一个魅力)。您不必编写大量样板代码,并且完全掌控实际发生的事情。此外,您可以获得强大的打字功能,从而提高了开发人员的生产力以及可维护性,并且可以使其他LOC合法化。当然,强大的输入意味着强大的工具!

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

希望这可以成为灵感的人遇到类似的问题。

干杯!

+0

感谢您的洞察,我觉得它非常有帮助。我最近开始与Grails一起构建一个项目,而且我得出的结论和你所做的一样。我选择理解权衡,许多好东西和坏人。但是,这种对非编组复杂对象的限制对我来说是一个很大的惊喜。现在,我有第二个想法,回到Spring MVC + Spring Data。我唯一想错过的是GSP。我发现GSP,特别是sitemesh,非常强大。你知道任何可以和Spring MVC一起使用的技术和GSP一样吗? –

+0

看看Thymeleaf。它与GSP有着非常类似的目标。 –