I am de-serializing a JSON object with the ObjectMapper class in java. I am getting objects of different types (? extends Something) and wanted to know if there is any开发者_JAVA技巧 way to de-serialize them in some generic way. The readValue method gets some Class type object of the type of the output object so it is somehow strongly typed.
Jackson can take not only type-erased class as target type, but also TypeReference which uses the usual "super type token" pattern. From Jackson FAQ:
List<MyBean> result = mapper.readValue(src, new TypeReference<List<MyBean>>() { });
and this works for all kinds of generic types, not just Maps and Collections. This in case you were thinking of generic types; so that you just have a single class but multiple parametric variations.
But it sounds like maybe what you want is actually support for deserializing polymorphic types; and this is also support (as of Jackson 1.5, see http://wiki.fasterxml.com/JacksonPolymorphicDeserialization).
EDIT: given sample classes in the other answer, Jackson way would be to do:
import org.codehaus.jackson.annotate.JsonTypeInfo;
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)
public abstract class Message
{
protected Message(){ }
}
and deserialize by:
Message msg = objectMapper.readValue(json, Message.class);
to get any sub-class of Message. And serialize using 'objectMapper.writeValue();'
Have you tried JSON in Java?
I have been using Json-lib library to accomplish this goal and was quite pleased with the results. Have look at the library examples http://json-lib.sourceforge.net/ You can register custom morphers that would transform nested elements of json into proper classes. I was able to get pretty complicated structures from json to java and access all nested fields.
Hope it helps
Here is an answer I came to:
First of all I have switched from ObjectMapper to Gson. Define an abstract class and an enum of types:
public abstract class Message {
private MessageType type;
protected Message(){
type = setType();
}
protected abstract MessageType setType();
public MessageType getType() {
return type;
}
public void setType(MessageType type) {
this.type = type;
}
}
public enum MessageType {
PRESENCE(PresenceMessage.class),
TEXT(TextMessage.class);
private Class<? extends Message> clazz;
private MessageType(Class<? extends Message> clazz){
this.clazz = clazz;
}
public Class<? extends Message> getClazz() {
return clazz;
}
}
Every class that extends the Message is the actual one we are sending over Json. It has to implement the getType() method.
So when desirializing just use that code :
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(get.getResponseBodyAsStream(),"UTF-8"));
while ((line = reader.readLine()) != null){
builder.append(line);
}
if (clazz == Message.class){
String string = builder.toString();
Message message = gson.fromJson(string,Message.class);
if (message.getType() == null)
throw new IllegalStateException("Could not de-serialize message " + builder.toString() );
return (T)gson.fromJson(string,message.getType().getClazz());
}
I hope you can fill the missing parts by yourself.
GSON dude. https://sites.google.com/site/gson/gson-user-guide#TOC-Object-Examples
精彩评论