Grails JSON Converters and transient properties - grails

Using Grail 1.3.7 I found that the JSON converter ignores transient properties of Domain objects.
Question: Is there an elegant way to work around this obstacle.
Bonus question: what's the reasoning behind excluding calculated fields(transient props) from being sent to the response????

what works for me is this one line
def jsonobj=domobj.properties as JSON

one way would be to manually create your json response, e.g.
["prop1" : obj.prop1, "prop2" : obj.prop2, ...] as JSON

Transient is made exactly for that: Variables may be marked transient to indicate that they are not part of the persistent state of an object
And JSON is an serialized (=persistent) state of object
So, if you need it to be serialized - you have to create an new class, just for json serialization, that will have all fields you need to serialize.

If you need fine-grained control over the fields that are included/excluded in the JSON, I fine using the JSONBuilder a better option than the converter. Here's an example of how to do this.

You could use the "marshallers" plug-in and define you transient property as virtual like this:
static marshalling = {
virtual {
yourPropery { value, json -> json.value(value.yourPropery) }
}
}

Related

How to use inheritance with Swift and ObjectMapper?

I'm new to Swift and I have to serialize an object structure into a JSON string in my iOS( iOS >= 8) project.
So I decided to use the ObjectMapper library (I integrated it with Cocoapod).
But my problem is that the structure is the following.
ObjectA can have a list of children objects as an array stored in an instance variable.
Objects that can be stored in the instance array can be of multiple types, say ObjectB and ObjectC. So, in Java with GSON I would have created an InterfaceD and made both of my classes implement it and made the array in ObjectA store InterfaceD types, but I can't figure how to do this with Swift object model as it results in empty {} JSON objects.
The resulting JSON should look like this.
{"children":[
{"type":"ObjectB", "value1":"foo"},
{"type":"ObjectC", "value1":"bar", "value2":"baz"}
]}
and I get
{"children":[
{},
{}
]}
Notice that the two entries that have to be serialized from objectA and ObjectC should have different structures.
I tried multiple things but each times I'm stuck in a dead end.
I tried using generics, tried to use Mappable protocol as my array type, I tried classic class inheritence but any one failed.
Have you any idea how I can achieve this ?
Note that I know that I could add a serialization function to each object and retrieve the strings recursively and concatenate them. But I really want to avoid implementing a JSON serializer by myself as I already use on successfully as Alamofire is already used in the project). Also implementing a new serializer is error prone and not a clean way to solve the problem IMO.
Thanks a lot.
I never had the solution but as a workaround I just made my objects produce a dictionnary from all its values. Then I recursively add child objects dictionnaries as the current dictionnary values.
It adds a toDict() function to each object that I forced with a protocol.
When the resulting object is only made of a tree of dictionnaries, the ObjectMapper serialization works fine...

Deserialise a Json object containing a Json String

I have a problem where I am unable to de-serialise a Json string to an object in cases where the object already has a Json string in it.
Ex:
Class A {
int a;
String jsonRpresenationOfSomeObject;
// other stuff
}
I am unable to de-serialise an object of the above Class A. I get an exception for the field "jsonRpresenationOfSomeObject"
Custom de-serialiser is not an option for my use case. Am looking for something generic.
Also found no luck with the Gson library.
Would appreciate any help on this.
There is no issue in serializing and deserializing in JSON for the above mentioned scenario of yours.
I have tried and found that the JSON is able to deserialize your class properly.
i think their might be problem with Access-Specifier of your class.
If you still face the problem, then prvide us the sample source.

Serializing JSON with configured serializer

I am using ASP.Net Web API with JSON.Net to serialize. I had to configure the serializer to handle ISO dates properly like this:
var iso = new IsoDateTimeConverter {
DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK"
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter
.SerializerSettings.Converters.Add(iso);
This works fine when I am passing my objects down via the WebAPI. My problem, however, is that I have another place where I want to explicitly call the serialization:
#Html.Raw(JsonConvert.SerializeObject(Model));
In this case, it doesn't use the configuration I set up. I am aware that I can pass the iso converter into the SerializeObject call, but I prefer to avoid this and get a hold of a configured serialzer for obvious reasons.
Any ideas?
If you're going to do JSON serialization yourself, you have to pass the settings you want explicitly. There's no way around it. The best I can think of if you want to reuse the same serializer settings is to do something like this:
JsonConvert.SerializeObject(Model, GlobalConfiguration.Configuration.Formatters.
JsonFormatter.SerializerSettings)

How to dynamically add a property / field to a domain class in Grails?

For a project I'm currently working on I need to dynamically add properties to a domain class and persist them later in the database. In general, I need a key/value store attached to a "normal" domain class. Sadly I cannot use a NoSQL database (e.g. Redis).
My approach would be to handle the additional properties on a save() by identifying them within afterInsert or afterUpdate and writing them to another table - I would prefer not to use a map property within the domain class but an additional "Field" table (to better support searches).
I tried to add properties using the metaClass approach:
person.metaClass.middlename = "Biterius"
assert person.middlename == "Biterius" // OK
This works and I can identify the additional properties in the afterInsert/afterUpdate methods but it seems that I cannot change the value thereafter - i.e., the following does not work:
person.middlename = "Tiberius"
assert person.middlename == "Tiberius" // FAIL
Then I tried an Expando approach by extending the Person class by the Expando class (directly ("Person extends Expando") and via an abstract intermediate class ("Person extends AbstractPerson" and "AbstractPerson extends Expando")).
def person = new Person()
assert person in Person // OK
assert person in AbstractPerson // OK
assert person in Expando // OK
Both variants did not work - I could assign values to arbitrary "properties" but the values were not stored!
person.mynewproperty = "Tiberius" // no MissingPropertyException is thrown
println person.mynewproperty // returns null
So how can I add properties to a domain class programmatically during runtime, change them and retrieve them during afterInsert or afterUpdate in order to "manually" store them in a "Fields" table?
Or am I doing something completely wrong? Are there other / simpler ways to do this?
What about turning your DB into a "NoSQL" one?
In one of my projects, I just used a String-property to store a map as JSON-Object.
For Groovy it's not a big problem to convert between a map and a JSON-Object. And since you can access a map just like an object with properties, I found this solution very convenient.
Only drawback: you have to plan the size of your String-property in advance...
Update: sorry, just read that you want to support searches...
what about
class Person {
...
static hasMany = [extProperties:KeyValue]
...
def invokeMethod(String name, args) {
if (name.startsWith('get')) {
//an unknown properties's getter is called
}
//add same for setter
}
}
class KeyValue {
String key
String value
}
I guess such a schema would give you all freedom you need. Even without the hasMany, you can make use of invokeMethod to handle your external tables...
The getter and setter can save your values in a transient string propertie (static transients = ['myTransientProperty']). This property should be available in the afterInsert / `afterUpdate´ events.
Why don't you just create a map of strings on the domain object and store your extra data there manually? Unless you're storing complex data you should be able to cast anything you need to/from a string.

Grails: easiest way to persist hashmap in GORM

I am generating a big nasty ruby-style hashmap, and rather than re-factor to well described objects i just want to hang this beastliness quickly onto a domain object. Is there any EASY way to store this hashmap without having to write a bunch of .toBytes getters and setters?
class EasyObjectStorer{
Object thing
}
Would be just super. So I can go:
def makeThisThing = new EasyObjectStorer()
makeThisThing.thing=['allala':'laalla','etc':'etc']
makeThisThing.save(failOnError:true)
Just store it as a String and use evaluate() to hydrate it back to a hashmap.
def a = "['allala':'33','etc':'1']"
def result = evaluate( a )
println result.etc
Be aware your keys need to be 'strings' using this method.

Resources