Fontanka16
Fontanka16

Reputation: 1321

Serializing Joda DateTime using groovy.json

I have this simple pojo class Fueling that i want to serialize to JSON using the built in Groovy JSON Library. However my application halts when trying to serialize.

class Fueling {
int id;
int mileage;
double amount;
double cost;
DateTime dateTime;
String userId;

}

the following tests renders a java.lang.StackOverflowError:

@Test
void parseJoda(){
    def fueling = new Fueling(amount: 1.0, cost: 2.3, mileage: 123, dateTime: DateTime.now(DateTimeZone.UTC));
    def jsonF = JsonOutput.toJson(fueling);

}

How can i make this serialization work?

EDIT: The JSON data is for persisting and not for display purpuses, so the actual serialization result format is not important just as long as i am able to get it deserialized again

Upvotes: 1

Views: 527

Answers (1)

bdkosher
bdkosher

Reputation: 5883

Given you don't care about the format, one simple workaround is to use Maps as your Groovy JSON API input/output and then add in a little code to translate your domain objects to and from Maps.

Serializing

You can use the Map that is returned by getProperties as-is with two modifications: converting the DateTime instance to it's long millisecond representation and removing the class entry (which lead to memory errors for me)

def serialize(){
    def fueling = new Fueling(amount: 1.0, cost: 2.3, mileage: 123, dateTime: DateTime.now(DateTimeZone.UTC));
    JsonOutput.toJson(
        fueling.properties.collectEntries { k, v -> 
            [(k): k == 'dateTime' ? v.millis : v] // represent DateTime as milliseconds
        }.findAll { 
            it.key != 'class' // remove the unnecessary 'class' property
        }
    ) 
}

Deserializing

You can pass the Map that the JsonSlurper spits out directly to your Fueling constructor with the slight modification of converting the dateTime entry from long back to a DateTime instance

def deserialize() {
    String json = '{"userId":null,"cost":2.3,"id":0,"dateTime":1439839235603,"amount":1.0,"mileage":123}'
    Map props = new JsonSlurper().parseText(json)
    new Fueling(props.collectEntries { k, v -> 
        [(k): k == 'dateTime' ? new DateTime(v) : v ] // convert back to DateTime
    })
}

Of course, there comes a point when your domain object tree is large/complex enough to warrant the use of a more extensible 3rd-party JSON library.

Upvotes: 3

Related Questions