【问题标题】:Grails render encodeAsJSON GORM with ObjectId (mongodb)Grails 使用 ObjectId (mongodb) 渲染 encodeAsJSON GORM
【发布时间】:2011-03-03 00:06:54
【问题描述】:

这是一个模型

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 进行编码,所以一切都被“转义”了......

那么您认为解决方案是什么,让构建器始终定义我想要返回的内容?

希望,我已经把我的问题说清楚了......

我将从builder开始,希望您能给我另一个更简单/更清洁的解决方案...

谢谢

编辑 我刚刚做了一个将对象作为地图返回的方法,所以现在我做了这样的事情

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

【问题讨论】:

  • 我刚刚做了一个将对象作为地图返回的方法,所以现在我做了类似这样的事情 render(status:200, contentType:"application/json") { ['foo' : getFooAsMap(Foo .get(params.id))] }

标签: json serialization grails mongodb


【解决方案1】:

在 Bootstarp.groovy 注册这个 objectMarshaller,它会像一个魅力一样工作

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

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

【讨论】:

  • 在 Grails 3 的 Bootstrap.groovy 中似乎不适合我。
【解决方案2】:

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

【讨论】:

  • 您好,感谢您的建议,但我认为,我将继续使用 ObjectId 和将对象作为 Map 返回的方法。在页面mongodb.org/display/DOCS/Object+IDs(对象ID与分片和分发更协同)谢谢!
【解决方案3】:

在您的地图中使用 GStrings,您将获得 ObjectId 的数值。 例如

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

【讨论】:

    【解决方案4】:

    你也可以这样做:

    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)
    }
    

    【讨论】:

      【解决方案5】:

      只需将您的域类定义为

      class Foo {  
        String id  
        String name 
      
      }
      

      而不是 ObjectId

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-20
        • 1970-01-01
        • 2010-11-30
        • 2011-05-17
        • 2015-02-18
        • 2013-02-07
        • 2014-08-25
        相关资源
        最近更新 更多