如何在不修改外部类时为JSON集合添加类名以生成可反序列化XML?
问题描述
我正在编写一个泛型转换器,需要将任意JSON转换为可反序列化的有效XML,但无法修改生成JSON的外部模型类。
假设使用以下Java类生成JSON:
class Wrapper { private List<Item> items; } class Item { private int id; private String name; }
生成的JSON如下:
{"Wrapper":{"items":[{"id":1,"name":"A"},{"id":2,"name":"B"}]}}
此时JSON中丢失了Item类名信息,直接用JSONObject类库转换得到的XML格式无法反序列化:
<Wrapper> <items><name>A</name><id>1</id></items> <items><name>B</name><id>2</id></items> </Wrapper>
预期的有效XML格式应该包含Item对应的包裹节点:
<Wrapper> <items> <item> <name>A</name> <id>1</id> </item> <item> <name>B</name> <id>2</id> </item> </items> </Wrapper>
我希望在不修改外部模型类的前提下,让JSON集合中包含Item的类名信息,生成类似如下格式的JSON:
{"Wrapper":{"items":[{"type":"TestDataBuilder$Item","id":1,"name":"A"},{"type":"TestDataBuilder$Item","id":2,"name":"B"}]}}
可行方案
不需要修改原有模型类,有几种方式可以实现需求:
1. 使用Jackson的Mixin机制
Mixin可以在不修改原类的情况下,为类添加Jackson注解:
// 定义Item的Mixin接口,添加类型信息注解 interface ItemMixin { @JsonTypeInfo( use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type" ) void setId(int id); void setName(String name); } // 配置ObjectMapper并注册Mixin ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Item.class, ItemMixin.class); // 序列化Wrapper对象即可生成带type字段的JSON Wrapper wrapper = new Wrapper(); // 填充items数据逻辑... String jsonWithType = mapper.writeValueAsString(wrapper);
2. 自定义Jackson序列化器
为Item类编写自定义序列化器,手动写入类型字段:
class ItemSerializer extends StdSerializer<Item> { public ItemSerializer() { super(Item.class); } @Override public void serialize(Item item, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); // 写入类全名作为type字段值 gen.writeStringField("type", item.getClass().getName()); // 写入原有字段 gen.writeNumberField("id", item.getId()); gen.writeStringField("name", item.getName()); gen.writeEndObject(); } } // 注册序列化器到ObjectMapper ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(Item.class, new ItemSerializer()); mapper.registerModule(module);
3. 若无法控制JSON生成环节,修改原始JSON
如果已经拿到了不带type字段的JSON,可以先解析并修改:
String originalJson = "{\"Wrapper\":{\"items\":[{\"id\":1,\"name\":\"A\"},{\"id\":2,\"name\":\"B\"}]}}"; ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(originalJson); // 定位到items数组节点 ArrayNode itemsArray = (ArrayNode) root.get("Wrapper").get("items"); for (JsonNode itemNode : itemsArray) { // 为每个元素添加type字段 ((ObjectNode) itemNode).put("type", "TestDataBuilder$Item"); } // 生成修改后的JSON String modifiedJson = mapper.writeValueAsString(root);
有了带type字段的JSON后,在转换XML时就可以根据该字段识别元素类型,生成对应的<item>包裹节点,得到符合要求的可反序列化XML。
内容的提问来源于stack exchange,提问作者Piotr Rezmer
相关产品推荐
相关产品推荐

