Я использую XStream и сериализатор JSON JETTISON Stax JSON для отправки / получения сообщений в / из клиентов JSON javascripts и веб-приложений Java.
Я хочу иметь возможность создавать список объектов для отправки на сервер и правильного распределения в Java, но формат, в котором XStream и JSON ожидают его, очень неинтуитивен и требует, чтобы наши библиотеки javascript перепрыгивали через обручи.
[РЕДАКТИРОВАТЬ Обновление проблемы с использованием GSON библиотека]
Я попытался использовать библиотеку GSON , но она не может десериализовать конкретные объекты, если у меня есть только ожидаемые универсальные суперклассы (XStream и Jettison обрабатывают это, потому что информация о типе запекается в сериализации).
GSON FAQ заявляет Ограничение Коллекции :
Ограничения коллекций
Может сериализовать коллекцию произвольных объектов, но не может десериализовать из нее
Поскольку пользователь не может указать тип получаемого объекта
При десериализации, Collection должен иметь определенный универсальный тип
Может быть, я использую плохие практики Java, но как бы мне построить систему обмена сообщениями JSON to Java, которая отправляла / получала различные конкретные объекты сообщений в формате JSON?
Например, это не получается:
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 имеют одинаковый тип, а третий - другой тип.
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 ?
Есть ли у кого-нибудь предложение для хорошей сериализации Java-объектов JSON, которая позволяет вам читать / записывать произвольные Java-объекты. Я посмотрел на JSON-процессор Джексона Java , но когда вы читали объекты из потока, вы должны были указать, какой тип объекта он отличается от XStream, где он будет считываться в любом объекте (поскольку сериализованный XStream JSON содержит информация об имени класса).