使用 Groovy 将 bean 序列化和反序列化为 json

Wav*_*vyx 6 java groovy serialization json deserialization

我已经用 groovy http://www.infoq.com/news/2014/04/groovy-2.3-json阅读了有关 json 的新闻。所以我尝试使用本地方法来(反)序列化包含日期的 groovy bean。但是我在将 JsonOutput.toJson(object) 与 JsonObject.fromObject() 与 java.util.Date 一起使用时遇到了问题

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

在 groovy 2.3+ 中使用本机方法的正确方法是什么?

否则,我可以去另一个像 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
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:我也尝试过使用 JsonSlurper,但总是得到 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
    }
}
Run Code Online (Sandbox Code Playgroud)

Wav*_*vyx 6

解决方法

我找到了一个解决方法,但总的来说,Json(反)序列化与日期相当混乱......

虽然http://groovy-lang.org/json.html声明支持 java.util.date,但它仍然依赖于“旧”RFC 822“yyyy-MM-dd'T'HH:mm:ssZ”,请参阅https: //docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html#timezone(Java 6.0 及更低版本)

Java 7.0 通过“yyyy-MM-dd'T'HH:mm:ss.SSSXXX”引入了 ISO 8601 支持

这个错误http://jira.codehaus.org/browse/GROOVY-6854仍然存在于 Groovy 2.3.7 中。此外,默认的 JsonSlurper 默认情况下不转换日期。只有 JsonParserLax 和 JsonFastParser 似乎关心日期解析,因此您需要强制使用正确的解析器类型。

当前基于 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)
}
Run Code Online (Sandbox Code Playgroud)

我希望 JSON 的(反)序列化约定将在即将发布的版本中得到执行。

为了完整起见,我还尝试了其他库,这是我的其他测试:

恩惠

Boon 0.30 在序列化 Groovy 对象(metaClass)时迷失并抛出 org.boon.Exceptions$SoftenedException“检测到循环依赖”

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)
}
Run Code Online (Sandbox Code Playgroud)

格森

Gson 2.3.1开箱即用,但序列化为本地日期格式:{"name":"John","re​​gistration":"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)
}
Run Code Online (Sandbox Code Playgroud)

杰克逊

Jackson 2.4.4 开箱即用,但序列化为纪元毫秒格式:{
"name":"John","re​​gistration":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)
}
Run Code Online (Sandbox Code Playgroud)