我想将JSON字符串转换为java对象,但此对象的类包含杰克逊无法实例化的抽象字段,并且不生成该对象.告诉它关于抽象类的一些默认实现的最简单方法是什么,比如
setDefault(AbstractAnimal.class, Cat.class);
Run Code Online (Sandbox Code Playgroud)
或者根据JSON属性名称来决定实现类,例如.对于JSON对象:
{
...
cat: {...}
...
}
Run Code Online (Sandbox Code Playgroud)
我愿意:
setImpl("cat", Cat.class);
Run Code Online (Sandbox Code Playgroud)
我知道Jackson可以在JSON中嵌入类信息,但我不想让我使用的JSON格式复杂化.我想通过设置默认实现类或属性名称('cat')来决定使用哪个类 - 就像在XStream库中一样,您可以在其中编写:
xStream.alias("cat", Cat.class);
Run Code Online (Sandbox Code Playgroud)
有没有办法这样做,特别是在一行中,还是需要更多的代码?
我正在使用JacksonPolymorphicDeserialization,这是我的代码,它反序列化为基于'type'属性的正确类:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
defaultImpl = Event.class,
visible = true)
@JsonSubTypes({
@Type(value = SpecialEvent1.class, name = "SPECIAL_EVENT_1"),
@Type(value = SpecialEvent2.class, name = "SPECIAL_EVENT_2"),
})
public abstract class AbstractEvent {
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好,我的json根据'type'值变成了预期的类.
但是,我正在考虑将'type'属性从String移动到Enum,这是我的新代码:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
defaultImpl = Event.class,
visible = true)
@JsonSubTypes({
@Type(value = SpecialEvent1.class, …Run Code Online (Sandbox Code Playgroud) 如果我有这样的类结构:
public abstract class Parent {
private Long id;
...
}
public class SubClassA extends Parent {
private String stringA;
private Integer intA;
...
}
public class SubClassB extends Parent {
private String stringB;
private Integer intB;
...
}
Run Code Online (Sandbox Code Playgroud)
是否有另一种方法来反序列化不同的@JsonTypeInfo呢?在我的父类上使用此批注:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "objectType")
Run Code Online (Sandbox Code Playgroud)
我宁愿不必强制我的API的客户端包括"objectType": "SubClassA"反序列化子Parent类.
@JsonTypeInfo杰克逊是否提供了一种注释子类并通过唯一属性将其与其他子类区分开来的方式,而不是使用?在上面的示例中,这将是"如果JSON对象"stringA": ...将其反序列化为SubClassA,如果它已将其"stringB": ...反序列化为SubClassB".
假设序列化为json包含实际对象的类名,在Class上使用此批注:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type")
class MyClass {
String foo;
}
Run Code Online (Sandbox Code Playgroud)
所以json就是这样的:
{"@type": "com.example.MyClass", "foo": "bar"}
Run Code Online (Sandbox Code Playgroud)
可以在不指定类型的情况下反序列化吗?我的意思是甚至不是超级型.就像这样:
objectMapper.readValue(value, Object.class);
Run Code Online (Sandbox Code Playgroud)
它实际上没有用,它带回了一张地图.
我想做的事
我想使用Jackson对多态类型进行反序列化,使用标准@JsonTypeInfo注释如下:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = As.EXISTING_PROPERTY,
property = "identifier")
@JsonSubTypes({@Type(value = A.class, name = "A"),
@Type(value = B.class, name = "B")})
abstract Class Base {}
Class A implements Base {
public String identifier = "A";
}
Class B implements Base {
public String identifier = "B";
}
Class Decorated {
public String decoration = "DECORATION";
@JsonUnwrapped
public Base base;
}
/*
Serialized instance of Decorated WITHOUT @JsonUnwrapped:
{
"decoration" : "DECORATION",
"base" : {
"identifier" : …Run Code Online (Sandbox Code Playgroud) 类人:
@Data
public class Person<T extends Parent> implements Serializable {
private static final long serialVersionUID = 7822965786010192978L;
private static final ObjectMapper objectMapper = new ObjectMapper();
private String id;
private T people; // change (String peopleInfo) to object extends Parent after read data from database
private String peopleInfo; // change (T people) to string and save in the dataBase as an string
@SneakyThrows
public void setPeople(T people) {
this.people = people;
peopleInfo = objectMapper.writeValueAsString(people);
}
@SneakyThrows
public void setPeopleInfo(String peopleInfo) { …Run Code Online (Sandbox Code Playgroud) 假设我有以下课程:
public class Animal {
public string name;
public int age;
public bool canBark;
}
public class Dog : Animal {
}
Run Code Online (Sandbox Code Playgroud)
并实例化Animal如下:
Animal a = new Animal();
Run Code Online (Sandbox Code Playgroud)
无论如何Dog在创建实例后将该实例下转换为实例?还是我被迫认识到我Animal是Dog在创造它的时候?我遇到此问题的原因是因为我的实例是通过调用工厂类创建的,该工厂类返回基于我提供的JSON文件的类型.该canBark属性值是通过查看该文件的几个看似不相关的领域进行计算.Dog通过查看canBark字段而不是那些JSON字段来确定某些内容是更有意义的.
public class AnimalFactory{
public static Animal Create(JObject json){
Animal a = new Animal();
a.canBark = (json["someField"]["someOtherField"].ToString() == "abc")
.....
}
Run Code Online (Sandbox Code Playgroud)
我现在通过在Dog类中使用构造函数来解决这个问题,该构造函数将其Animal作为参数并简单地将该实例的变量的值分配给它自己.但这不是一种非常灵活的方式,因为每次添加字段时我都需要在每个子类构造函数中添加一行.
那么,是通过将该决策移动到实例创建来确定类型的最佳方法还是还有其他方法?