Jon*_*oll 62 java polymorphism json compiler-errors jackson
我试图通过程序员布鲁斯的一个教程来完成,该教程应该允许多态JSON的反序列化.
完整的列表可以在这里找到 程序员布鲁斯教程(伟大的东西顺便说一句)
我已经完成了前五个没有问题,但我在最后一个(示例6)遇到了障碍,当然这是我真正需要工作的那个.
我在编译时遇到以下错误
ObjectMapper类型中的方法readValue(JsonParser,Class)不适用于参数(ObjectNode,Class)
它是由大量代码引起的
public Animal deserialize(
JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends Animal> animalClass = null;
Iterator<Entry<String, JsonNode>> elementsIterator =
root.getFields();
while (elementsIterator.hasNext())
{
Entry<String, JsonNode> element=elementsIterator.next();
String name = element.getKey();
if (registry.containsKey(name))
{
animalClass = registry.get(name);
break;
}
}
if (animalClass == null) return null;
return mapper.readValue(root, animalClass);
}
}
Run Code Online (Sandbox Code Playgroud)
具体由行
return mapper.readValue(root,animalClass);
有没有人遇到过这个问题,如果有的话,是否有解决方案?
我很感激任何人都可以给予任何帮助.
jba*_*eta 110
正如所承诺的,我正在举例说明如何使用注释来序列化/反序列化多态对象,我在Animal
您正在阅读的教程的类中基于此示例.
首先,您的Animal
类包含子类的Json Annotations.
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "Dog"),
@JsonSubTypes.Type(value = Cat.class, name = "Cat") }
)
public abstract class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的子类,Dog
和Cat
.
public class Dog extends Animal {
private String breed;
public Dog() {
}
public Dog(String name, String breed) {
setName(name);
setBreed(breed);
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
}
public class Cat extends Animal {
public String getFavoriteToy() {
return favoriteToy;
}
public Cat() {}
public Cat(String name, String favoriteToy) {
setName(name);
setFavoriteToy(favoriteToy);
}
public void setFavoriteToy(String favoriteToy) {
this.favoriteToy = favoriteToy;
}
private String favoriteToy;
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,没有什么特别的Cat
和Dog
,即了解他们的唯一一个是abstract
类Animal
,所以反序列化时,就定位于Animal
与ObjectMapper
返回的实际情况,你可以在下面的测试中看到:
public class Test {
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
Animal myDog = new Dog("ruffus","english shepherd");
Animal myCat = new Cat("goya", "mice");
try {
String dogJson = objectMapper.writeValueAsString(myDog);
System.out.println(dogJson);
Animal deserializedDog = objectMapper.readValue(dogJson, Animal.class);
System.out.println("Deserialized dogJson Class: " + deserializedDog.getClass().getSimpleName());
String catJson = objectMapper.writeValueAsString(myCat);
Animal deseriliazedCat = objectMapper.readValue(catJson, Animal.class);
System.out.println("Deserialized catJson Class: " + deseriliazedCat.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行Test
类后输出:
{"@type":"Dog","name":"ruffus","breed":"english shepherd"}
Deserialized dogJson Class: Dog
{"@type":"Cat","name":"goya","favoriteToy":"mice"}
Deserialized catJson Class: Cat
希望这可以帮助,
何塞路易斯
Mar*_*rco 16
您只需要在类声明前一行就可以Animal
进行正确的多态序列化/反序列化:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public abstract class Animal {
...
}
Run Code Online (Sandbox Code Playgroud)
此行表示:在序列化时添加元属性或在反序列化时读取元属性 ( include = JsonTypeInfo.As.PROPERTY
),称为“@class”( property = "@class"
),其中包含完全限定的 Java 类名 ( use = JsonTypeInfo.Id.CLASS
)。
因此,如果您直接创建 JSON(不进行序列化),请记住添加具有所需类名的元属性“@class”以进行正确的反序列化。
更多信息在这里
虽然@jbarrueta 的答案是完美的,但在 2.12 版本的 Jackson 中引入了一个新的期待已久的@JsonTypeInfo
注释类型DEDUCTION
.
当您无法更改传入的 json 或不得更改时,它很有用。我仍然建议使用use = JsonTypeInfo.Id.NAME
,因为在无法确定使用哪个子类型的复杂情况下,新方法可能会抛出异常。
现在你可以简单地写
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
@JsonSubTypes.Type(Dog.class),
@JsonSubTypes.Type(Cat.class) }
)
public abstract class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
它会产生{"name":"ruffus", "breed":"english shepherd"}
和{"name":"goya", "favoriteToy":"mice"}
再一次,NAME
如果某些字段可能不存在,则使用更安全,例如breed
或favoriteToy
。
通过 Jackson 库启用多态序列化/反序列化的一个简单方法是全局配置 Jackson 对象映射器 (jackson.databind.ObjectMapper) 来为某些类型的类(例如抽象类)添加信息,例如具体类类型。
为此,只需确保您的映射器配置正确即可。例如:
选项 1:支持抽象类(和对象类型类)的多态序列化/反序列化
jacksonObjectMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
Run Code Online (Sandbox Code Playgroud)
选项 2:支持抽象类(和对象类型类)以及这些类型的数组的多态序列化/反序列化。
jacksonObjectMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
Run Code Online (Sandbox Code Playgroud)
参考: https: //github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
归档时间: |
|
查看次数: |
81149 次 |
最近记录: |