Grails使用ObjectId(mongodb)渲染encodeAsJSON GORM

时间:2011-03-03 00:06:55

标签: json serialization grails mongodb

这是一个模型

import org.bson.types.ObjectId

class Foo{  
 ObjectId id  
 String name 

}

这是一个动作

def action = {
 render(status:200, contentType:"application/json") {
    ['foo' : Foo.get(params.id)]
 }
}

该操作将返回类似这样的内容

{"foo":{"class":"Foo","id":{"class":"org.bson.types.ObjectId","inc":340737392,"machine":-2019394572,"new":false,"time":1299107672000},"name":"fooName"]}

我的问题是,如何在json中发送ObjectId的toString,我不想要这个

"id":{"class":"org.bson.types.ObjectId","inc":340737392,"machine":-2019394572,"new":false,"time":1299107672000}

我想要更像

的东西
"id":18893828183

我知道我可以选择我想要的参数:

def foo = Foo.get(params.id)
['foo' : 'Foo' :[id:foo.id.toString(), name:foo.name]]

但是我不想总是声明我想要以json的形式返回,我想要返回所有对象,Foo.get(params.id).encodeAsJSON()......

有没有办法覆盖encodeAsJSON()

我已经尝试添加此

class Foo{
 ....

 static transients : ['idStr']

 def getIdStr(){
     return this.id.toString()
 }
 ....
}

但它在encodeAsJSON()

中被忽略了

我甚至试过这个

class Foo{
 ....
 def toJSON(){
        def obj =  this.encodeAsJSON() 
        def json = new JsonSlurper().parseText(obj);
        json.idString = this.id.toString()
        return json.toString()
    }
...
}

这“有效”,但没有......

因为在此之后

 render(status:200, contentType:"application/json") {
    ['foo' : Foo.get(params.id).toJSON()]
 }

渲染对json进行编码,因此所有内容都被“转义”....

那么您认为解决方案是什么,建设者总是定义我想要返回的内容?

希望,我明白了我的问题......

我将从建造者开始,希望你能给我一个更简单/更清洁的解决方案......

由于

修改的 我刚刚做了一个将对象作为地图返回的方法,所以现在我做了类似的事情

render(status:200, contentType:"application/json") { 
   ['foo' : getFooAsMap(Foo.get(params.id))] 
}

5 个答案:

答案 0 :(得分:3)

在Bootstarp.groovy注册此objectMarshaller,它将像魅力一样工作

import grails.converters.JSON
import org.bson.types.ObjectId

JSON.registerObjectMarshaller(ObjectId) {
        return it.toStringMongod()
}

答案 1 :(得分:0)

如果你要将你的域类JSON编码到网上,我想知道ObjectId是不是最好的选择? GORM / MongoDB集成允许您使用任何类型的id。您可以将它声明为String类型(如果您希望将其用于随机性,则可以将其指定为ObjectId的toString),然后您不必担心这种混乱。任何性能/可伸缩性问题都可以在以后进行分析/处理,但除非是非常大型应用程序,否则我不会指望有任何问题。

答案 2 :(得分:0)

在地图中使用GStrings,您将获得ObjectId的数值。 E.g。

render ["foo":"$foo.id"] as JSON

答案 3 :(得分:0)

您也可以这样做:

def domainObj = YourDomainClass.get(params.id)

Map props = [:]
def domain = new DefaultGrailsDomainClass(YourDomainClass.class)
domain.properties.each{
    props[it.name] = domainObj[it.name]
}

props["id"] = domainObj.id.toString()

render props as JSON

或者更好,让它可重复使用。把这个封闭放在一个方便的地方:

def mongoObjectResponse = {dobj ->

    Map props = [:]
    def domain = new DefaultGrailsDomainClass(YourDomainClass.class)
    domain.properties.each{
        props[it.name] = dobj[it.name]
    }

    props["id"] = dobj.id.toString()

    // I like to leave room in my responses for messages and such
    message = ""
    obj = props
}

然后从你的控制器那样打电话:

return render(contentType: "text/json") {
    mongoObjectResponse.delegate = delegate
    mongoObjectResponse(domainObj)
}

答案 4 :(得分:0)

只需将您的域类定义为

即可
class Foo {  
  String id  
  String name 

}

而不是ObjectId