在XStream中,有一种更好的方法可以在JSON和Java中对List <Object>进行编组/解组

Dou*_*kem 9 java ajax serialization json xstream

我正在使用XStream和JETTISON的Stax JSON序列化程序向/从JSON javascripts客户端和Java Web应用程序发送/接收消息.

我希望能够创建一个发送到服务器的对象列表,并将其正确编组到Java中,但XStream和JSON期望它的格式非常不直观,并且需要我们的javascript库跳过箍.

[使用GSON库编辑更新问题]我试图使用GSON库但是当我只有它期望泛型超类时,它不能反序列化具体对象(XStream和Jettison处理这个因为类型信息被烘焙到序列化中).

GSON FAQ声明收集限制:

收藏限制

可以序列化任意对象的集合,但不能从中反序列化

因为用户无法指示结果对象的类型

在反序列化时,Collection必须是特定的泛型类型

也许我正在使用糟糕的java实践,但我如何构建一个JSON到Java消息传递框架,以JSON格式发送/接收各种具体的Message对象?

例如,这失败了:

public static void main(String[] args) {
    Gson gson = new Gson();

    MockMessage mock1 = new MockMessage();
    MockMessage mock2 = new MockMessage();
    MockMessageOther mock3 = new MockMessageOther();

    List<MockMessage> messages = new ArrayList<MockMessage>();
    messages.add(mock1);
    messages.add(mock2);
    messages.add(mock3);

    String jsonString = gson.toJson(messages);

    //JSON list format is non-intuitive single element array with class name fields
    System.out.println(jsonString);
    List gsonJSONUnmarshalledMessages = (List)gson.fromJson(jsonString, List.class);
    //This will print 3 messages unmarshalled
    System.out.println("XStream format JSON Number of messages unmarshalled: " + gsonJSONUnmarshalledMessages.size());
}

[{"val":1},{"val":1},{"otherVal":1,"val":1}]
Exception in thread "main" com.google.gson.JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@638bd7f1 failed to deserialized json object [{"val":1},{"val":1},{"otherVal":1,"val":1}] given the type interface java.util.List
Run Code Online (Sandbox Code Playgroud)

这是一个例子,我想发送一个包含3个Message对象的列表,2个是相同类型的,3是不同类型.

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;

class MockMessage {
    int val = 1;
}
class MockMessageOther {
    int otherVal = 1;
}

public class TestJSONXStream {


    public static void main(String[] args) {
        JettisonMappedXmlDriver xmlDriver = new JettisonMappedXmlDriver();        
        XStream xstream = new XStream(xmlDriver);

        MockMessage mock1 = new MockMessage();
        MockMessage mock2 = new MockMessage();
        MockMessageOther mock3 = new MockMessageOther();

        List messages = new ArrayList();
        messages.add(mock1);
        messages.add(mock2);
        messages.add(mock3);

        String jsonString = xstream.toXML(messages);

        //JSON list format is non-intuitive single element array with class name fields
        System.out.println(jsonString);
        List xstreamJSONUnmarshalledMessages = (List)xstream.fromXML(jsonString);
        //This will print 3 messages unmarshalled
        System.out.println("XStream format JSON Number of messages unmarshalled: " + xstreamJSONUnmarshalledMessages.size());

        //Attempt to deserialize a reasonable looking JSON string
        String jsonTest = 
              "{"+
                "\"list\" : ["+ 
                          "{"+
                          "\"MockMessage\" : {"+
                              "\"val\" : 1"+
                          "}"+
                      "}, {"+
                          "\"MockMessage\" : {"+
                              "\"val\" : 1"+
                          "}"+
                      "}, {"+
                          "\"MockMessageOther\" : {"+
                              "\"otherVal\" : 1"+
                          "}"+
                      "} ]"+
                  "};";

        List unmarshalledMessages = (List)xstream.fromXML(jsonTest);

        //We expect 3 messages but XStream only deserializes one
        System.out.println("Normal format JSON Number of messages unmarshalled: " + unmarshalledMessages.size());
    }

}
Run Code Online (Sandbox Code Playgroud)

直观地说,我希望从以下格式序列化XStream JSON(并能够正确地反序列化):

{
    "list" : [ 
        {
        "MockMessage" : {
            "val" : 1
        }
    }, {
        "MockMessage" : {
            "val" : 1
        }
    }, {
        "MockMessageOther" : {
            "otherVal" : 1
        }
    } ]
}
Run Code Online (Sandbox Code Playgroud)

相反,XStream会创建一个单独的元素列表,其中包含名为类名的字段和相同类型的对象的嵌套数组.

{
    "list" : [ {
        "MockMessage" : [ {
            "val" : 1
        }, {
            "val" : 1
        } ],
        "MockMessageOther" : {
            "otherVal" : 1
        }
    } ]
}
Run Code Online (Sandbox Code Playgroud)

使用XStream XML CollectionConverter可能导致问题?

有没有人建议一个好的JSON Java对象序列化,允许你读/写任意Java对象.我查看了Jackson Java JSON处理器,但是当您从流中读取对象时,您必须指定它与XStream不同的对象类型,它将在任何对象中读取(因为序列化的XStream JSON包含类名信息).

Sta*_*Man 6

我同意其他海报,因为XStream不太合适 - 它是一个OXM(对象/ Xml映射器),JSON使用XML处理路径作为辅助输出格式处理.这就是为什么需要一个"约定"(如何将层次结构xml模型转换为json的对象图模型,反之亦然); 而你的选择归结为使用任何次要的次优选择.如果XML是您的主要数据格式,那么这是可行的,您只需要一些基本的JSON(类似)支持.

为了获得良好的JSON支持,我会考虑使用一个真正的OJM映射的JSON处理库(我假设Svenson也这样做,但另外),例如:

另外:即使你确实需要同时支持XML和JSON,你最好还是为这些任务使用单独的库 - 在服务器端使用的对象(bean)不需要不同,只是转换为/从的序列化库xml和json.