gpt4 book ai didi

java - Jackson 反序列化是否有继承深度的最大值?

转载 作者:太空宇宙 更新时间:2023-11-04 09:34:01 25 4
gpt4 key购买 nike

换句话说,可以实现的继承深度是有限制的。目前我的深度为 2,祖 parent -> parent -> child ,我遇到了一个问题,Jackson 可以反序列化到 parent ,然后抛出 UnrecognizedPropertyException。这是正确的,但是子类确实拥有该属性,并且我相信我已经为 Jackson 添加了正确的类型信息来反序列化子类。

此测试显示了问题:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Value;
import lombok.experimental.SuperBuilder;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class JacksonInheritanceTest {

@Test
public void deserializeChildrenAsGrandParentList() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String grandparentsJson = "{" +
"\"list\":[{" +
"\"type\": \"parent\"," +
"\"value\": \"child\"," +
"\"someProperty\": \"foobar\"" +
"}]" +
"}";
GrandParentList grandparents = mapper.readValue(grandparentsJson, GrandParentList.class);
Assert.assertNotNull(grandparents);
}

@Test
public void deserializeParentAsGrandParent() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String parentJson = "{" +
"\"type\": \"parent\"," +
"\"value\": \"child\"" +
"}";
GrandParent grandparent = mapper.readValue(parentJson, GrandParent.class);
Assert.assertNotNull(grandparent);
}

@Test
public void deserializeChildAsGrandParent() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String grandparentJson = "{" +
"\"type\": \"parent\"," +
"\"value\": \"child\"," +
"\"someProperty\": \"foobar\"" +
"}";
GrandParent grandparent = mapper.readValue(grandparentJson, GrandParent.class);
Assert.assertNotNull(grandparent);
}

@Test
public void deserializeChildAsParent() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String childJson = "{" +
"\"type\": \"parent\"," +
"\"value\": \"child\"," +
"\"someProperty\": \"foobar\"" +
"}";
Parent parent = mapper.readValue(childJson, Parent.class);
Assert.assertNotNull(parent);
}

@Test
public void deserializeAsChild() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String child1 = "{" +
"\"type\": \"parent\"," +
"\"value\": \"child\"," +
"\"someProperty\": \"foobar\"" +
"}";
Child child = mapper.readValue(child1, Child.class);
Assert.assertNotNull(child);
}
}

class GrandParentList {
@JsonProperty
List<GrandParent> list;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = Parent.class,
name = "parent")
})
@Getter
@SuperBuilder
@JsonDeserialize(builder = GrandParent.GrandParentBuilderImpl.class)
class GrandParent {
@JsonProperty("type")
private String type;

@JsonPOJOBuilder(withPrefix = "")
static final class GrandParentBuilderImpl extends GrandParentBuilder<GrandParent, GrandParent.GrandParentBuilderImpl> {
}
}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "value", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = Child.class, name = "child")
})
@Getter
@SuperBuilder
@JsonDeserialize(builder = Parent.ParentBuilderImpl.class)
class Parent extends GrandParent {
@JsonProperty
private String value;

@JsonPOJOBuilder(withPrefix = "")
static final class ParentBuilderImpl extends ParentBuilder<Parent, ParentBuilderImpl> {
}
}


@EqualsAndHashCode(callSuper = true)
@Value
@SuperBuilder
@JsonDeserialize(builder = Child.ChildBuilderImpl.class)
class Child extends Parent {
@JsonProperty
private String someProperty;

@JsonPOJOBuilder(withPrefix = "")
static final class ChildBuilderImpl extends ChildBuilder<Child, ChildBuilderImpl> {
}
}

最佳答案

以下是如何定义多个级别的继承:

您想要反序列化最终类型为“child”的 GrandParent 列表

  {
"list":[{
"type": "child",
"someProperty": "foobar"
}]
}

继承树是:

GrandParent
Parent
Child(someProperty:String)

您必须在顶层定义“类型”属性,@JsonTypeInfo(...) 您可以在子级别上重复它,但如果您仅序列化/反序列化祖 parent ,则不需要这样做。然后在每个父级(Parent 类和 GrandParent 类)上定义子类型,就像使用 @JsonSubTypes 一样。

代码

public class JacksonInheritanceTest2 {

@Test
public void deserializeChildrenAsGrandParentList() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String grandparentsJson = "{" +
"\"list\":[{" +
"\"type\": \"child\"," +
"\"someProperty\": \"foobar\"" +
"}]" +
"}";
GrandParentList grandparents = mapper.readValue(grandparentsJson, GrandParentList.class);
Assertions.assertNotNull(grandparents);
}


}

class GrandParentList {
@JsonProperty
List<GrandParent> list;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = Parent.class,name = "parent"),
//@JsonSubTypes.Type(value = Child.class, name = "child")
})
class GrandParent {
@JsonProperty("type")
private String type;

}


//@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = Child.class, name = "child")
})
class Parent extends GrandParent {
@JsonProperty
private String value;

}

@JsonSubTypes({
@JsonSubTypes.Type(value = Child.class, name = "child")
})
class Child extends Parent {
@JsonProperty
private String someProperty;

public String getSomeProperty() {
return someProperty;
}

public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}



}

您犯的错误:

  • 定义多个属性类型名称,每个属性类型名称对应一个父级别:您可以选择属性类型名称并仅使用一个。
  • 在 Json 中,您确实在摘要中设置了父级的类型名称:只有叶子类型很重要,树的其余部分被扣除。

侧节点:Assertions 来自 junit5,它的作用与来自 junit4 的 Assert 相同

关于java - Jackson 反序列化是否有继承深度的最大值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56733933/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com