我正在使用XStream和JETTISON的Stax JSON序列化器向JSON javascript客户端和Java Web应用程序发送消息/从接收消息。
我希望能够创建一个对象列表以发送到服务器并正确地编码为Java,但是XStream和JSON期望它使用的格式非常不直观,并且需要我们的JavaScript库来跳过。
[编辑使用GSON库的更新问题]
我尝试使用GSON library,但是当我只期望普通的父类(super class)时,它无法反序列化具体对象(XStream和Jettison会处理此问题,因为类型信息已烘焙到序列化中)。
GSON FAQ states Collection Limitation:
也许我使用了不良的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
这是一个示例,我要发送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());
}
}
直观地,我期望XStream JSON从以下格式进行序列化(并能够正确反序列化):
{
"list" : [
{
"MockMessage" : {
"val" : 1
}
}, {
"MockMessage" : {
"val" : 1
}
}, {
"MockMessageOther" : {
"otherVal" : 1
}
} ]
}
取而代之的是,XStream使用具有相同名称的类名和嵌套数组的字段创建具有字段的单个元素列表。
{
"list" : [ {
"MockMessage" : [ {
"val" : 1
}, {
"val" : 1
} ],
"MockMessageOther" : {
"otherVal" : 1
}
} ]
}
使用XStream XML的CollectionConverter可能是造成问题的原因?
是否有人建议对JSON Java对象进行良好的序列化,从而允许您读取/写入任意Java对象。我查看了Jackson Java JSON Processor,但是当您从流中读取对象时,必须指定它与XStream不同的对象类型,因为XStream可以在任何对象中读取(因为序列化的XStream JSON包含类名信息)。
最佳答案
我同意其他张贴者的观点,因为XStream不合适,它是OXM(对象/Xml映射器),并且JSON使用XML处理路径作为辅助输出格式进行处理。这就是为什么需要“约定”(关于如何将hierarchich xml模型转换为json的对象图模型,反之亦然)的原因;而您的选择归结为使用对次优选择影响最小的选项。
如果XML是您的主要数据格式,那还行,您只需要一些基本的JSON(-like)支持即可。
为了获得良好的JSON支持,我会考虑使用执行真正OJM映射的JSON处理库(我假设Svenson也这样做),例如:
另外:即使您确实需要同时支持XML和JSON,也最好将这些任务使用单独的库来使用IMO-在服务器端使用的对象(beans)不必有所不同,只需将序列库转换为或从中进行转换即可。 xml和json。
关于java - 在XStream中,有一种更好的方法来编码/解码JSON和Java中的List <Object>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/836805/