需引入
Jackson
依赖,可参考 Jackson 使用简介 。
@JsonTypeInfo 序列化
1)定义序列化结构
@Data
public class LiveLesson {
public static final TypeReference ITEMS_TYPE = new TypeReference() {
};
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Container {
private List- items;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public interface Item {
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Item1 implements Item {
private long id;
private String item1Name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Item2 implements Item {
private long id;
private String item2Name;
}
}
2)测试代码
public class TestMain {
public static void main(String[] args) {
List items = new ArrayList<>();
items.add(new LiveLesson.Item1(1, "Item1"));
items.add(new LiveLesson.Item2(2, "Item2"));
LiveLesson.Container container = new LiveLesson.Container(items);
System.out.println(serialize(items));
System.out.println(serialize(container));
}
private static final ObjectMapper objectMapper = new ObjectMapper();
@SneakyThrows
public static String serialize(Object obj) {
return objectMapper.writeValueAsString(obj);
}
}
控制台输出:
[{"id":1,"item1Name":"Item1"},{"id":2,"item2Name":"Item2"}]
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
可以发现不通过类进行包裹的话,序列化后不会出现 @c
字段。
@JsonTypeInfo 反序列化
public class TestMain {
public static void main(String[] args) {
List items = new ArrayList<>();
items.add(new LiveLesson.Item1(1, "Item1"));
items.add(new LiveLesson.Item2(2, "Item2"));
LiveLesson.Container container = new LiveLesson.Container(items);
String serialize = serialize(container);
System.out.println(serialize);
LiveLesson.Container newContainer = deserialize(serialize, LiveLesson.ITEMS_TYPE);
System.out.println(serialize(newContainer));
}
private static final ObjectMapper objectMapper = new ObjectMapper();
@SneakyThrows
public static String serialize(Object obj) {
return objectMapper.writeValueAsString(obj);
}
@SneakyThrows
public static T deserialize(String json, TypeReference valueTypeRef) {
return objectMapper.readValue(json, valueTypeRef);
}
}
控制台输出:
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
变更路径后的反序列化
1)定义反序列化结构
除了
LiveLesson
变更为LiveLessonInfo
,其他的结构和上面的一样。
@Data
public class LiveLessonInfo {
public static final TypeReference ITEMS_TYPE = new TypeReference() {
};
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Container {
private List- items;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public interface Item {
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Item1 implements Item {
private long id;
private String item1Name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Item2 implements Item {
private long id;
private String item2Name;
}
}
2)测试代码
public static void main(String[] args) {
List items = new ArrayList<>();
items.add(new LiveLesson.Item1(1, "Item1"));
items.add(new LiveLesson.Item2(2, "Item2"));
LiveLesson.Container container = new LiveLesson.Container(items);
String serialize = serialize(container);
System.out.println(serialize);
// LiveLesson.ITEMS_TYPE 修改为 LiveLessonInfo.ITEMS_TYPE
LiveLesson.Container newContainer = deserialize(serialize, LiveLesson.ITEMS_TYPE);
System.out.println(serialize(newContainer));
}
控制台输出:
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'org.company.jackson.LiveLesson$Item1' as a subtype of `org.company.jackson.LiveLessonInfo$Item`: Not a subtype
at [Source: (String)"{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}"; line: 1, column: 17] (through reference chain: org.company.jackson.LiveLessonInfo$Container["items"]->java.util.ArrayList[0])
3)使用 JsonTypeInfo.Id.NAME
替换 JsonTypeInfo.Id.MINIMAL_CLASS
,新增 @JsonSubTypes
注解。
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public interface Item {
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@c")
@JsonSubTypes({
@JsonSubTypes.Type(value = Item1.class, name = ".LiveLesson$Item1"),
@JsonSubTypes.Type(value = Item2.class, name = ".LiveLesson$Item2")
})
public interface Item {
}
执行测试代码,控制台输出:
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
{"items":[{"@c":".LiveLesson$Item1","id":1,"item1Name":"Item1"},{"@c":".LiveLesson$Item2","id":2,"item2Name":"Item2"}]}
参考
- Jackson使用
@JsonSubTypes
实现多态解析