当前位置: 首页 > 知识库问答 >
问题:

Jackson2.1.2多态反序列化引发JSONMappingException。为什么?

蔺德曜
2023-03-14

简单地说,我能够让Jackson2.1.2将类层次结构序列化为带有类型信息的JSON字符串。但是,我无法让Jackson2.1.2将JSON字符串反序列化回到我类层次结构中。下面是一个暴露这个问题的单元测试。

类层次结构足够简单;只有两个直接子类的基类。此外,JSON输出似乎尊重我的Jackson@JsonTypeInfo,并从Mapper.WriteValueString生成一个可信的字符串

{"type":"dog","name":"King","breed":"Collie"}

但我对mapper.readvalue(jsonOfKing,animal.class)的调用堆栈跟踪了...

FAILED: testJacksonSerializeDeserialize
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.rekdev.fasterjacksonwtf.PolymorphismTests$Dog]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.StringReader@32b3a5a0; line: 1, column: 14]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:400)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
....
import org.testng.annotations.*;
import static org.testng.Assert.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.databind.*;

public class PolymorphismTests {
    @Test
    public void testJacksonSerializeDeserialize() throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        Animal king = new Dog();
        king.name = "King";
        ( (Dog) king ).breed = "Collie";
        String jsonOfKing = mapper.writeValueAsString( king );
        // JsonMappingException right here!
        Animal actualKing = mapper.readValue( jsonOfKing, Animal.class );
        assertEquals( king, actualKing );

    }

    @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" )
    @JsonSubTypes( { @Type( value = Cat.class, name = "cat" ), @Type( value = Dog.class, name = "dog" ) } )
    abstract class Animal {
        public String name;

        @Override
        public abstract boolean equals( Object obj );

        @Override
        public abstract int hashCode();
    }

    class Dog extends Animal {
        public String breed;

        @Override
        public boolean equals( Object obj ) {
            if ( this == obj ) {
                return true;
            }
            if ( obj == null ) {
                return false;
            }
            if ( getClass() != obj.getClass() ) {
                return false;
            }
            final Dog that = (Dog) obj;
            boolean equals = name.equals( that.name ) && breed.equals( that.breed );
            return equals;
        }

        @Override
        public int hashCode() {
            int hashCode = name.hashCode() + breed.hashCode();
            return hashCode;
        }
    }

    class Cat extends Animal {
        public String favoriteToy;

        @Override
        public boolean equals( Object obj ) {
            if ( this == obj ) {
                return true;
            }
            if ( obj == null ) {
                return false;
            }
            if ( getClass() != obj.getClass() ) {
                return false;
            }
            final Cat that = (Cat) obj;
            boolean equals = name.equals( that.name ) && favoriteToy.equals( that.favoriteToy );
            return equals;
        }

        @Override
        public int hashCode() {
            int hashCode = name.hashCode() + favoriteToy.hashCode();
            return hashCode;
        }
    }
}

共有1个答案

邹俊友
2023-03-14

使内部类静态化,例如:

static class Dog extends Animal { ... }

否则将无法工作(因为非静态内部类需要所谓的“Implicit this”参数来引用封闭类的实例)。

 类似资料:
  • 我正在开发一个应用程序,它使用Gson作为JSON反序列化器,需要从REST API反序列化多态JSON。在解释mi问题之前,请注意,我已经用Gson研究了多态反序列化,并在几个案例中成功地实现了它。这是我面临的一个具体问题。在问这个问题之前,我也读过这篇很棒的帖子和关于堆栈溢出的讨论。顺便说一下,我正在使用RuntimeTypeAdapterFactory来反序列化多态对象。 我遇到的问题是,G

  • 我对Jackson和类型层次结构有以下问题。我正在序列化一个类SubA,该类将扩展为一个字符串,然后尝试将其反序列化回来。当然,在编译时,系统不知道它是基还是SubA,因此我希望它是基,如果它是SubA,则会在编译后执行一些其他操作。 我的基本类看起来像: ...和一个派生自的类: ... 我试图执行以下代码: String是: 但我一次又一次地犯同样的错误。映射器现在知道如何处理另一个类参数-它

  • 问题内容: 使用取消序列化对象时出现以下错误: JSONMappingException无法构造org.springframework.data.Page的实例,问题:抽象类型只能用其他类型信息实例化。 我正在尝试将JSON字符串序列化为表示类型页面的Spring数据对象T。 该User班是一个简单的与和名称。我要反序列化的字符串是: 这将导致异常: 由于是对象,因此无法修改它,我认为这与我在别处

  • 问题内容: 我正在尝试使用Jackson将json数据转换为POJO对象。这是MainActivity和我的POJO类代码。我基本上收到了JsonMappingException错误。我还附上了整个日志。 MainActivity.java: Entries.java(这是POJO) 现在,我的日志中出现以下错误。因此,我无法继续工作。这是日志: 问题答案: 在 条目* 和 电话中 删除构造函数

  • 我想为我们的REST API实现一个自定义的反序列化器,它不仅被Java应用程序使用。因此,我不想让Jackson将类型信息放入序列化的JSON中。 我目前正在努力反序列化<code>CollectionExpand</code>,因为它包含特定<code>ResourceModel</code>的<code>数据</code>列表。 < code>ResourceModel是一个接口,每个< c

  • 我有一个接口,其中和实现。服务器会返回这样的响应- 相应的类来建模它是 中的声明它是哪种车辆。我需要反序列化的成一个对象取决于。如果是,我需要在反序列化和期间使用反序列化。 如何使用gson实现这一点? 编辑-这篇文章的不同之处在于类类型()包含在需要反序列化的中。这里不是。如果在内,我可以为编写自定义反序列化程序,检查,并进行相应的反序列化。但是我想我需要为编写一个自定义反序列化程序,在这里我创