【发布时间】:2017-11-19 00:16:25
【问题描述】:
我已经研究了实现 Objects 类的最佳方法,继承并包含在一个对象中作为一个列表。
- 链接1:How to configure Jackson to deserialize named types with default typing?
- 链接2:https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
- 链接3:http://www.davismol.net/2015/03/05/jackson-json-deserialize-a-list-of-objects-of-subclasses-of-an-abstract-class/
如果您知道任何处理该场景并提供正确答案的链接,我将很乐意接受此重复项并关闭此项目。 我有以下课程:
动物园
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.List;
import lombok.*;
@Getter
@Setter
@Builder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Zoo {
private String zooName;
private String zooLocation;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private @Singular List<Animal> animals;
}
动物
@Getter
@Setter
@Builder(builderMethodName = "parentBuilder")
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NONE,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
defaultImpl = Animal.class
)
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Elephant.class, name = "elephant")
})
public class Animal{
private String type;
private String nameTag;
}
狗
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@JsonPropertyOrder({ "type", "nameTag"})
@JsonTypeName("dog")
public class Dog extends Animal{
private String barkingPower;
}
大象
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@JsonPropertyOrder({ "type", "nameTag"})
public class Elephant extends Animal{
private String weight;
}
模型助手
public final class ModelHelper {
private static final ObjectMapper MAPPER = new ObjectMapper();
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.enableDefaultTypingAsProperty(
ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, "type");
public static <T> T fromJson(@NotNull final String json, final Class<T> objectClass) {
try {
return MAPPER.readValue(json, objectClass);
} catch (Exception e) {
final String message = String.format("Error de-serialising JSON '%s' to object of %s",
json, objectClass.getName());
log.warn(message, e);
return null;
}
}
}
我正在使用 ModelHelper 将 JSON 反序列化为对象:
String json = "{\"zooName\":\"Sydney Zoo\",\"zooLocation\":\"Sydney\",\"animals\":[{\"type\":\"dog\",\"nameTag\":\"Dog1\",\"barkingPower\":\"loud\"},{\"type\":\"elephant\",\"nameTag\":\"Elephant1\",\"weight\":\"heavy\"}]}";
mapper.readValue(json, Zoo.class);
目前Zoo 的反序列化只返回Animal 属性,而不是Dog 或Elephant 属性。
我的问题是:
- 我可以收集到的是反序列化不起作用,因为
Zoo中List<Animal>的 getter 是基类类型,反序列化无法确定如何创建Dog或Elephant,并且基于在签名时它会生成Animal。但是我会认为通过放置JsonTypeName和JsonSubTypes注释我已经标记了相关的子类。是这样吗? -
Animal类是否必须定义为abstract才能正常工作? - 让这个工作的唯一方法是实现类 Zoo 的自定义反序列化吗?这是一个很好的例子吗:https://www.sghill.net/how-do-i-write-a-jackson-json-serializer-deserializer.html?
如果代码不清楚,请告诉我,我会修复它。
【问题讨论】:
-
这个例子真的需要
DefaultZoo吗(我们不知道它是什么)?Zoo已经持有列表。 -
这不是必须的,但这是目前的实现方式。我会更新并删除。
标签: java json jackson polymorphism deserialization