6

I have a grails object that I am converting using def json = object as JSON. After I have it converted I want to add one more property called pin to the JSON which looks like the following.

[location:[lat:23.03, lon:72.58]]

Only way to do this so far seems like following

  1. Serialize the DomainClass to JSON using grails.converters.json
  2. Convert the JSON to string
  3. Create JSONBoject using the string from Step 2
  4. Add the property
  5. Convert it back to String

Any other way to do this using grails.converters.json? I have tried using Gson but I do not want to go that route because I am getting many Circular Reference Errors

tim_yates
  • 167,322
  • 27
  • 342
  • 338
Sap
  • 5,197
  • 8
  • 59
  • 101

2 Answers2

2

Try this:

domainInstance.properties + [pin: pinInstance] as JSON
Alexander Tokarev
  • 2,743
  • 2
  • 20
  • 21
  • Would this add pin as part of domain instance? – Sap Jan 21 '14 at 11:39
  • No, it wouldn't. But do you really need to merge your domain with additional fields? If so, maybe it will be better to add this field to your domain class? Or to make a surrogate field in it, providing a getter for `pin`? – Alexander Tokarev Jan 21 '14 at 11:46
  • That was my first attempt, I added lat and lon in the domain class and created `public getPin() { ['location':[lat:lat,lon:lon]] }` method but when I do `object as JSON` pin does not come in the string representation of the JSON – Sap Jan 21 '14 at 11:52
  • 1
    Had looked at the source code of `org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller`, and found that only persistent properties of domain class are marshalled to JSON. So, the most straightforward way to get a JSON with custom structure is via creation of a Map and marshalling it. – Alexander Tokarev Jan 21 '14 at 12:21
  • Is there a way to get corresponding map of a domainobject? – Sap Jan 21 '14 at 12:29
  • Try `domainInstance.properties`. I've edited my answer. – Alexander Tokarev Jan 21 '14 at 12:44
  • There must be some kind of member object that is not letting this happne. When I do toString on the result json i get `Error converting Bean with class org.h2.jdbc.JdbcResultSet` – Sap Jan 23 '14 at 09:59
  • An issue I had with this solution, is that it added a lot of extraneous properties that I did not want in my response, such as includes, excludes, etc – adeady Apr 05 '16 at 15:07
0

I recently needed to do a similar thing. Some caveats:

  • This is using Grails 2.4.5
  • I use MongoDB as a backend. As such, I created an object marshaller for MongoDB domain classes. It is printed below, and you can wrap a similar marshaller for your domain class(es):

Marshaller:

class MongodbObjectMarshaller implements ObjectMarshaller<JSON> {
    @Override
    boolean supports(Object o) { return o?.properties?.dbo }

    @Override
    void marshalObject(Object obj, JSON converter) throws    
    ConverterException {

        Map propertiesToOutput = obj.properties.dbo

        propertiesToOutput.remove("_id")  //don't print org.bson.types.ObjectId
        propertiesToOutput.remove("version")  //don't print gorm verson column

        converter.build {
            _id obj.id.toString()
            propertiesToOutput.each{ entry ->
                "$entry.key" entry.value
            }
        }

    }
}

What that marshaller does, it allow in JSON output any of the domain class's properties. obj.properties.dbo is special to MongoDB, but for a regular domain class, you can just grab the properties and exclude the ones you don't need.

Then in my controller, this works:

domainInstance.pin = [location:[lat:23.03, lon:72.58]]
def content = tacticalCard as JSON

because my marshaller now picks up the pin property and prints it.

aldrin
  • 4,482
  • 1
  • 33
  • 50
adeady
  • 467
  • 1
  • 4
  • 19