In XStream is there a better way to marshall/unmarshall List<Object>'s in JSON and Java
I agree with other poster in that XStream is not a good fit -- it's an OXM (Object/Xml Mapper), and JSON is handled as a secondary output format using XML processing path. This is why a "convention" (of how to convert hierarchich xml model into object-graph model of json and vice versa) is needed; and your choice boils down to using whatever is least intrusive of sub-optimal choices.That works ok if XML is your primary data format, and you just need some rudimentary JSON(-like) support.
To get good JSON-support, I would consider using a JSON processing library that does real OJM mapping (I assume Svenson does too, but additionally), such as:
Also: even if you do need to support both XML and JSON, you are IMO better off using separate libraries for these tasks -- objects (beans) to use on server-side need not be different, just serialization libs that convert to/from xml and json.
I realize this is off-topic, but I'd like to present a solution in svenson JSON.
Do you really need public fields in your domain classes? Apart from having to use properties, svenson can handle cases like this with a more simple JSON output with a discriminator property
class Message{ // .. your properties with getters and setters .. // special property "type" acts a signal for conversion}class MessageOther{ ...}List list = new ArrayList();list.add(new Message());list.add(new MessageOther());list.add(new Message());String jsonDataSet = JSON.defaultJSON().forValue(list);
would output JSON like
[ {"type":"message", ... }, {"type":"message_other", ... }, {"type":"message", ... }]
which could be parsed again with code like this
// configure reusable parse instance JSONParser parser = new JSONParser(); // type mapper to map to your types PropertyValueBasedTypeMapper mapper = new PropertyValueBasedTypeMapper(); mapper.setParsePathInfo("[]"); mapper.addFieldValueMapping("message", Message.class); mapper.addFieldValueMapping("message_other", MessageOther.class); parser.setTypeMapper(mapper); List list = parser.parse(List.class, jsonDataset);
A svenson type mapper based on the full class name would look something like this
public class ClassNameBasedTypeMapper extends PropertyValueBasedTypeMapper{ protected Class getTypeHintFromTypeProperty(String value) throws IllegalStateException { try { return Class.forName(value); } catch (ClassNotFoundException e) { throw new IllegalStateException(value + " is no valid class", e); } }}
which is not an ideal implementation as it inherits the configuration of PropertyValueBasedTypeMapper without really needing. (should include a cleaner version in svenson)
The setup is very much like above
JSONParser parser = new JSONParser();ClassNameBasedTypeMapper mapper = new ClassNameBasedTypeMapper();mapper.setParsePathInfo("[]");parser.setTypeMapper(mapper);List foos = parser .parse( List.class, "[{\"type\":\"package.Foo\"},{\"type\":\"package.Bar\"}]");