如何用Jackson序列化/反序列化含List<BaseMessage<Object>>的Envelope
解决方案
方案1:Jackson注解配置(优先推荐)
针对Envelope中List<BaseMessage<Object>>的泛型声明限制,通过两处注解补充类型信息:
- 指定泛型参数
ps的实际类型
在BaseMessage的ps字段添加注解,告诉Jackson将Object类型的ps反序列化为MessageData:
public abstract class BaseMessage<TData> { // ... 其他代码 @JsonDeserialize(as = MessageData.class) public TData ps; public SpanContext s; // ... 其他代码 }
- 明确集合元素的多态类型
在Envelope的payload字段添加注解,让Jackson识别集合元素是BaseMessage的子类,配合已有的@JsonTypeInfo完成类型匹配:
public class Envelope { @JsonDeserialize(contentAs = BaseMessage.class) public List<BaseMessage<Object>> payload; // ... 其他字段 }
配置完成后,序列化/反序列化直接使用ObjectMapper即可:
ObjectMapper mapper = new ObjectMapper(); // 序列化 String json = mapper.writeValueAsString(envelope); // 反序列化 Envelope result = mapper.readValue(json, Envelope.class);
方案2:使用TypeReference
如果注解方式受限,可在反序列化时通过TypeReference明确指定完整的泛型类型,绕过Object泛型的限制:
ObjectMapper mapper = new ObjectMapper(); // 序列化无需额外处理 String json = mapper.writeValueAsString(envelope); // 反序列化时用TypeReference指定具体类型 Envelope deserialized = mapper.readValue(json, new TypeReference<Envelope>() {}); // 若单独处理payload列表 List<BaseMessage<MessageData>> payload = mapper.readValue( jsonPayload, new TypeReference<List<BaseMessage<MessageData>>>() {} );
Jackson会基于BaseMessage上的@JsonTypeInfo自动识别AMessage/BMessage,无需额外配置。
方案3:手动处理List
将payload改为List<JsonNode>,手动读取鉴别器字段n后完成类型转换:
- 修改
Envelope类:
public class Envelope { public List<JsonNode> payload; // ... 其他字段 }
- 序列化:将子类实例转为
JsonNode存入列表
ObjectMapper mapper = new ObjectMapper(); Envelope envelope = new Envelope(); envelope.payload = Arrays.asList( mapper.valueToTree(new AMessage()), mapper.valueToTree(new BMessage()) ); String json = mapper.writeValueAsString(envelope);
- 反序列化:遍历
JsonNode,根据n字段判断类型并转换
Envelope envelope = mapper.readValue(json, Envelope.class); List<BaseMessage<?>> payload = new ArrayList<>(); for (JsonNode node : envelope.payload) { String type = node.get("n").asText(); switch (type) { case "a": payload.add(mapper.treeToValue(node, AMessage.class)); break; case "b": payload.add(mapper.treeToValue(node, BMessage.class)); break; // 扩展其他类型的处理逻辑 } }
内容的提问来源于stack exchange,提问作者Henrik
相关产品推荐
相关产品推荐

