当前位置: 首页 > 面试题库 >

用Jackson将反序列化的JSON转换为多态类型-一个完整的示例给我一个编译错误

隆飞宇
2023-03-14
问题内容

我正在尝试浏览Programmer Bruce的教程,该教程应该允许多态JSON的反序列化。

完整列表可以在这里找到 Programmer
Bruce教程
(顺便说一句)

我已经完成了前五项工作,没有任何问题,但是我在最后一项中遇到了麻烦(示例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);
  }  
}

具体按行

返回mapper.readValue(root,animalClass);

之前有人遇到过这个问题吗?如果有,有解决方案吗?

任何人都可以给您的帮助,我将不胜感激。


问题答案:

如所承诺的,我将举一个如何使用注释对多态对象进行序列化/反序列化的示例,该示例基于Animal您正在阅读的教程中的类。

首先,在您的Animal类中使用子类的Json注释。

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;
    }

}

然后是您的子类DogCat

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;

}

如您所见,Catand并没有什么特别的Dog,唯一了解它们的是abstractclass
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();
        }

    }
}

运行Test该类后的输出:

{"@type":"Dog","name":"ruffus","breed":"english shepherd"}

Deserialized dogJson Class: Dog

{"@type":"Cat","name":"goya","favoriteToy":"mice"}

Deserialized catJson Class: Cat

希望这可以帮助,

何塞·路易斯



 类似资料:
  • 我看过jackson反序列化@JsonTypeInfo的一个例子,那就是: 我试过了,效果很好。现在的问题是,在示例类中,Cat和Dog是从Animal中引用的,我想避免这种情况。有没有一种方法可以将类型绑定从类动物中移除,并且仍然进行反序列化工作?谢谢

  • 问题内容: 如果我有这样的类结构: 还有另一种反序列化的方法吗?在父类上使用此注释: 我不想强迫我的API的客户包括反序列化一个子类。 杰克逊不是使用,而是提供了一种方法来注释子类并通过唯一属性将其与其他子类区分开来?在上面的示例中,这类似于“如果JSON对象将其反序列化为,如果它将其反序列化为”。 问题答案: 感觉像是应该使用的东西,但是我在文档中进行了选择,可以提供的任何属性似乎都不符合您所描

  • 我有一个外部服务,我用它来查询一些数据。数据将采用两种格式之一(第一种是“遗留”格式,但需要支持): 或 我想将其映射到以下POJO: 第二种格式的数据(是一个对象)应该像任何其他POJO一样进行反序列化,但给定第一种格式的数据(是字符串),要将其转换为的实例,我想调用

  • 我正在尝试使用Jakson反序列化一个嵌套的多态类型。也就是说,我的顶级类型引用了另一个多态类型,该类型最终由不抽象的类扩展。这不起作用,它会抛出一个异常。 下面是我尝试做的一个简化的例子。 我得到了关于抽象类型的标准异常。 让我解释一下我的用例。我有一个描述数据工作流的Json文档。我在“Level One”有一个抽象类型,描述对单个值的操作。我派生了一堆不是抽象的类,它们实现了公共操作(我用@

  • 是否有任何开箱即用的方法将单例json数组反序列化为相同类型的java pojo? 例如,我想要以下json: 反序列化为以下java POJO: 我尝试使用下面的类: 但是这失败了: 我知道我可以用这样的其他类包装事件POJO: 但我希望避免这种情况(以及避免自定义反序列化器) 任何帮助都将不胜感激。

  • 问题内容: 我有一个看起来像这样的json结构: 我想将其反序列化为对象列表,其中每个对象都是基类的子类。列表中的每一项都有不同的属性(href,src,text),因此我无法使用同一类来访问范围。相反,我想要一个普通类的三个子类。JSON列表中每个项目的type属性可用于决定使用哪个子类。例如,我可以有以下课程 有什么办法吗?还是有更好的方法来反序列化异构对象类型列表? 编辑: 我正在使用jso