Serialize & Deserialize bean to json with Groovy

13,224

Solution 1

Workaround

I found a workaround, but overall the Json (de)serialization is quite messy with dates...

While http://groovy-lang.org/json.html states support for java.util.date it still relies on the "old" RFC 822 "yyyy-MM-dd'T'HH:mm:ssZ" see https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html#timezone (Java 6.0 and below)

Java 7.0 introduced the ISO 8601 support with "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"

This bug http://jira.codehaus.org/browse/GROOVY-6854 is still present in Groovy 2.3.7. Moreover the default JsonSlurper is not converting date by default. Only JsonParserLax and JsonFastParser seems to care about Date parsing, so you need to force the right Parser type.

Current workaround based on GROOVY-6854:

public void serializationNative(){
    Contact contact = new Contact()
    contact.name = 'John'
    contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')

    def sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
    sdf.setTimeZone(TimeZone.getTimeZone('UTC'))
    JsonOutput.dateFormatter.set(sdf)
    String jsonData = JsonOutput.toJson(contact)
    println(jsonData)

    JsonSlurper slurper = new JsonSlurper().setType( JsonParserType.INDEX_OVERLAY )
    def object = slurper.parseText(jsonData)
    Contact reloadContact = new Contact(object)
}

I hope the (de)serialization conventions for JSON will be enforced in upcoming release.

For the sake of completeness, I also tried other libraries here are my other tests:

Boon

Boon 0.30 gets lost in serializing Groovy object (metaClass) and throws org.boon.Exceptions$SoftenedException for "Detected circular dependency"

public void serializationBoon(){
    Contact contact = new Contact()
    contact.name = 'John'
    contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')

    ObjectMapper mapper = JsonFactory.create()

    String jsonData = mapper.toJson(contact)
    println(jsonData)

    Contact reloadContact = mapper.fromJson(jsonData, Contact.class)
}

Gson

Gson 2.3.1 works out-of-the-box but serializes to a Local Date format: {"name":"John","registration":"Oct 20, 2011 12:00:00 AM"}

public void serializationGson(){
    Contact contact = new Contact()
    contact.name = 'John'
    contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')

    Gson gson = new Gson()

    String jsonData = gson.toJson(contact)
    println(jsonData)

    Contact reloadContact = gson.fromJson(jsonData, Contact.class)

    println(jsonData)
}

Jackson

Jackson 2.4.4 works out-of-the-box but serializes to epoch millisecond format:
{"name":"John","registration":1319061600000}

public void serializationJackson(){
    Contact contact = new Contact()
    contact.name = 'John'
    contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')

    com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();

    String jsonData = mapper.writeValueAsString(contact)
    println(jsonData)

    Contact reloadContact = mapper.readValue(jsonData, Contact.class)
}

Solution 2

Work arounds are good. Just want to update I used groovy 2.4.5 and the problem looks to be fixed.

Book b = new Book(isbn:'dfjkad',quantity: 6, price: 5.00, title: "our mork book",
        publishDate: Date.parse('dd/MM/yyyy', '20/10/2011'), publisher: "matt payne")
render JsonOutput.toJson(b)

outputs

{"publishDate":"2011-10-20T04:00:00+0000","title":"our mork book","publisher":"matt payne","isbn":"dfjkad","price":5.00,"quantity":6,"author":null}
Share:
13,224
Wavyx
Author by

Wavyx

Updated on June 07, 2022

Comments

  • Wavyx
    Wavyx almost 2 years

    I've read this news about json with groovy http://www.infoq.com/news/2014/04/groovy-2.3-json. So I tried to native methods to (de)serialization of groovy bean containing dates. But I have issues whent using JsonOutput.toJson(object) with JsonObject.fromObject() with java.util.Date

    String jsonDat a= groovy.json.JsonOutput.toJson(contact)
    Contact reloadContact = new Contact(net.sf.json.JSONObject.fromObject(jsonData))
    

    What is the right way to to this with native methods in groovy 2.3+ ?

    Otherwise, I could go for another library like gson (http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/)

    package test
    
    import groovy.json.JsonOutput
    import net.sf.json.JSONObject
    
    class JsonTest {
    
        public static void main(String[] args) {
            JsonTest test = new JsonTest()
            test.serialization()
        }
    
        public void serialization(){
            Contact contact = new Contact()
            contact.name = 'John'
            contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')
    
            String jsonData = JsonOutput.toJson(contact)
            println(jsonData)
    
            Object object = JSONObject.fromObject(jsonData)
            Contact reloadContact = new Contact(object)
    
            println(jsonData)
        }
    
        public class Contact{
            String name
            Date registration
        }
    }
    

    Edit: I also tried with JsonSlurper, but always get the GroovyCastException: Cannot cast object '2011-10-19T22:00:00+0000' with class 'java.lang.String' to class 'java.util.Date' package test

    import groovy.json.JsonOutput
    import groovy.json.JsonSlurper
    
    class JsonTest {
    
        public static void main(String[] args) {
            JsonTest test = new JsonTest()
            test.serialization()
        }
    
        public void serialization(){
            Contact contact = new Contact()
            contact.name = 'John'
            contact.registration = Date.parse('dd/MM/yyyy', '20/10/2011')
    
            String jsonData = JsonOutput.toJson(contact)
            println(jsonData)
    
            JsonSlurper slurper = new JsonSlurper()
            def object = slurper.parseText(jsonData)
            Contact reloadContact = new Contact(object)
    
            println(jsonData)
        }
    
        public class Contact{
            String name
            Date registration
        }
    }