我正在使用 java 中的ObjectMapper类反序列化 JSON 对象。我得到了不同类型的对象(?扩展了一些东西),并想知道是否有任何方法可以以某种通用方式对它们进行反序列化。readValue方法获取输出对象类型的一些 Class 类型对象,因此它在某种程度上是强类型的。
5 回答
Jackson 不仅可以将类型擦除的类作为目标类型,还可以使用通常的“超级类型令牌”模式的 TypeReference。来自杰克逊常见问题解答:
List<MyBean> result = mapper.readValue(src, new TypeReference<List<MyBean>>() { });
这适用于各种泛型类型,而不仅仅是 Maps 和 Collections。如果您正在考虑泛型类型,请这样做;这样您就只有一个类但有多个参数变体。
但听起来你想要的实际上是支持反序列化多态类型;这也是支持(从杰克逊 1.5 开始,请参阅http://wiki.fasterxml.com/JacksonPolymorphicDeserialization)。
编辑:给定另一个答案中的示例类,杰克逊的方法是:
import org.codehaus.jackson.annotate.JsonTypeInfo;
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)
public abstract class Message
{
protected Message(){ }
}
并通过以下方式反序列化:
Message msg = objectMapper.readValue(json, Message.class);
获取消息的任何子类。并使用 'objectMapper.writeValue();' 进行序列化
我一直在使用 Json-lib 库来实现这个目标,并且对结果非常满意。查看库示例http://json-lib.sourceforge.net/ 您可以注册自定义变形器,将 json 的嵌套元素转换为适当的类。我能够获得从 json 到 java 的非常复杂的结构并访问所有嵌套字段。
希望能帮助到你
这是我得到的答案:
首先,我已经从ObjectMapper切换到Gson。定义一个抽象类和一个类型的枚举:
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;
}
}
每个扩展 Message 的类都是我们通过 Json 发送的实际类。它必须实现 getType() 方法。
因此,在反序列化时只需使用该代码:
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());
}
我希望你能自己填补缺失的部分。