简体   繁体   English

Grails使用ObjectId(mongodb)渲染encodeAsJSON GORM

[英]Grails render encodeAsJSON GORM with ObjectId (mongodb)

Here is a Model 这是一个模型

import org.bson.types.ObjectId

class Foo{  
 ObjectId id  
 String name 

}

And here an action 这是一个动作

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

The action will return something like this 该动作将返回类似这样的内容

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

My question is, how can I send in the json the toString of the ObjectId, I don't want this 我的问题是,我该如何在json中发送ObjectId的toString,我不要这个

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

I want something more like 我想要更多类似的东西

"id":18893828183

I know I can select the parameters I want like: 我知道我可以选择想要的参数:

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

But I don't want to declare always what I want to return as json, I want to return all the object, Foo.get(params.id).encodeAsJSON()... 但是我不想总是声明要作为json返回的内容,我想返回所有对象Foo.get(params.id).encodeAsJSON()...

Is there a way to override encodeAsJSON() 有没有一种方法可以重写encodeAsJSON()

I already tried to add this 我已经尝试添加

class Foo{
 ....

 static transients : ['idStr']

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

But it's ignored in the encodeAsJSON() 但是在encodeAsJSON()中被忽略

I even tried this 我什至尝试过

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

this "works", but no.... 这个“作品”,但是不。

because after this 因为在此之后

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

the render encode the json, so everything is "escaped".... 渲染对json进行编码,因此所有内容都被“转义了”。

So what do you think is the solution, with a builder always defining what I want to return? 那么您认为解决方案是什么,而构建器总是定义我要返回的内容?

Hope, I made my question clear.... 希望,我已经明确了我的问题...。

I'll start with the builder, hope you can give me another simpler / cleaner solution... 我将从构建器开始,希望您能给我另一个更简单/更简洁的解决方案...

Thanks 谢谢

edit I just did a method that returns the object as a map so now I do something like this 编辑我只是做了一个将对象作为地图返回的方法,所以现在我做这样的事情

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

Register this objectMarshaller at Bootstarp.groovy and it will work like a charm 在Bootstarp.groovy上注册该对象Marshaller,它将像魅力一样工作

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

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

You can do this too: 你也可以这样做:

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

Or better yet, make it reusable. 或更妙的是,使其可重用。 Put this closure someplace handy: 将此闭合放置在方便的位置:

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
}

Then call like this from your controller: 然后从您的控制器中这样调用:

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

Just define your domain class as 只需将您的域类定义为

class Foo {  
  String id  
  String name 

}

Instead of ObjectId 代替ObjectId

If you're going to be JSON-encoding your domain classes out to the web, I wonder if ObjectId might not be the best choice? 如果您要对您的域类进行JSON编码到网络上,我想知道ObjectId是否不是最佳选择? The GORM/MongoDB integration allows you to use any type for the id. GORM / MongoDB集成允许您对ID使用任何类型。 You could just declare it as a String type (which can be assigned as a toString of an ObjectId if you like to use that for its randomness) and then you don't need to worry about this mess. 您可以将其声明为String类型(如果您出于随机性而希望将其分配为ObjectId的toString),则不必担心这种混乱。 Any performance/scalability problems from this could be analysed/dealt with later, but I wouldn't expect there to be any unless it's a very large app. 以后可能会分析/处理由此引起的任何性能/可伸缩性问题,但是除非它是一个非常大的应用程序,否则我不希望有任何问题。

Use GStrings in your map and you will get a numeric value for your ObjectId. 在地图中使用GStrings,您将获得ObjectId的数字值。 Eg 例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM