Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson无法创建已在ObjectMapper中注册的类的实例_Java_Json_Jackson_Json Deserialization - Fatal编程技术网

Java Jackson无法创建已在ObjectMapper中注册的类的实例

Java Jackson无法创建已在ObjectMapper中注册的类的实例,java,json,jackson,json-deserialization,Java,Json,Jackson,Json Deserialization,我有一个父对象和一个子对象。父对象可能多次包含相同的子对象,因此我仅序列化子对象一次,下一个实例仅由其ID引用。当我从子对象中删除@JsonIdentityInfo注释时,该对象将无错误地反序列化。对我来说,这感觉像是一个Jackson bug,但也许有人发现了我代码中的错误。我举了一个小例子来说明错误(使用的Jackson版本是2.9.4): 父类: import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.util.A

我有一个父对象和一个子对象。父对象可能多次包含相同的子对象,因此我仅序列化子对象一次,下一个实例仅由其ID引用。当我从子对象中删除@JsonIdentityInfo注释时,该对象将无错误地反序列化。对我来说,这感觉像是一个Jackson bug,但也许有人发现了我代码中的错误。我举了一个小例子来说明错误(使用的Jackson版本是2.9.4): 父类:

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.util.ArrayList;
import java.util.Collection;
import lombok.Getter;
import lombok.Setter;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
        property = "type", defaultImpl = TestClassParent.class)
public class TestClassParent {

    @Getter
    @Setter
    private ITestClassChild child1;

    @Getter
    @Setter
    private Collection<ITestClassChild> children;

    public TestClassParent(){
        child1 = new TestClassChild();
        children = new ArrayList<>();
        children.add(child1);
    }
}
界面:

import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
        property = "type", defaultImpl = ITestClassChild.class)
public interface ITestClassChild {
    public String getId();
}
测试用例:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import org.junit.Test;

public class TestClassImportExportTest{

    @Test
    public void test() throws JsonProcessingException, IOException{
        ObjectMapper om = new ObjectMapper();
        om.registerSubtypes(
                TestClassChild.class
        );
        TestClassParent original = new TestClassParent();
        String json = om.writerWithDefaultPrettyPrinter().writeValueAsString(original);
        TestClassParent imported = om.readValue(json, TestClassParent.class);
    }

}
在以下错误中执行测试结果:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `json.ITestClassChild` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{
  "type" : "TestClassParent",
  "child1" : {
    "type" : "TestClassChild",
    "id" : "1"
  },
  "children" : [ "1" ]
}"; line: 7, column: 18] (through reference chain: json.TestClassParent["children"]->java.util.ArrayList[0])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:178)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:88)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:254)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:189)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:130)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1171)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at json.TestClassImportExportTest.test(TestClassImportExportTest.java:18)

如上所述,从TestClassChild中删除@JsonIdentityInfo注释会使测试用例顺利通过。但是,我需要注释以获得正确的导入。该错误似乎是由使用collection+interface+id引起的,删除其中任何一个似乎都可以,我很高兴能得到任何帮助

Jackson无法构造
ITestClassChild
的对象,因为它是一个接口,与
JsonIdentityInfo
一样,它试图保持双向关系

您可以在此处阅读
JsonIdentityInfo
-

例如,With接口需要使用
@JsonSubTypes
指定要使用的类型-

@JsonSubTypes({@Type(value=TestClassChild.class,name=“child1”)})
公共接口ITestClassChild

请参阅此以获得更好的解释

二手-杰克逊2.8。下面是我的代码,我仍然使用输入得到相同的异常

{
“类型”:“TestClassParent”,
“儿童”:{
“类型”:“TestClassChild”,
“id”:“1”
}
}

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,
property=“type”,defaultImpl=TestClassParent.class)
类TestClassParent{
私家儿童;
/*私人收藏儿童*/
公共TestClassParent(){
//child=newtestclasschild();
/*children=newarraylist();
添加(child1)*/
}
公共ITestClassChild getChild(){
返回儿童;
}
公共void setChild(ITestClassChild){
这个孩子=孩子;
}
}
@JsonTypeInfo(使用=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,
property=“type”,defaultImpl=ITestClassChild.class)
接口ITestClassChild{
公共字符串getId();
}
@JsonTypeInfo(使用=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,
property=“type”,defaultImpl=TestClassChild.class)
@JsonIdentityInfo(生成器=ObjectedGenerators.PropertyGenerator.class,
property=“id”)
类TestClassChild实现ITestClassChild{
私有字符串id;
公共TestClassChild(){
id=“1”;
}
@凌驾
公共字符串getId(){
返回id;
}
}
但是,如果按如下方式使用输入,则不会得到异常,因为它会忽略属性

{
“类型”:“TestClassParent”,

}

因此,以下解决方法应该有效:

我为每个子类添加了一个自定义反序列化程序(使用@jsondeselliate(使用=TestClassChildDeserializer.class)注释该类),并为接口添加了一个自定义反序列化程序(也以相同的方式注释)。然后我反序列化对象(也许有办法使用默认的反序列化器?),并将对象添加到接口反序列化器中的静态哈希映射中

反序列化程序只不过获取节点的textValue并在HashMap中返回该节点的值。子反序列化程序反序列化对象并将其保存到HashMap中

它非常难看,但目前仍然有效(尽管我需要在反序列化后清空HashMap,而且它也不是线程安全的…)


我也尝试了这里提出的解决方案:没有用。

谢谢。我已经在对象映射器中注册了子类型,它应该可以很好地工作,而且确实可以。当我从TestClassParent(和构造函数)中删除Collection属性时,该类被正确序列化和反序列化,即使它包含另一个ITestClassChild属性(child1)。这意味着Jackson可以正确地处理接口,只是当它是集合的泛型类型时就不行了。我也尝试过你的建议,在接口上使用@JsonSubTypes(),但我仍然得到了相同的错误。我认为它仍然给出了例外。。请参考以上我的评论。谢谢你的帮助。
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `json.ITestClassChild` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{
  "type" : "TestClassParent",
  "child1" : {
    "type" : "TestClassChild",
    "id" : "1"
  },
  "children" : [ "1" ]
}"; line: 7, column: 18] (through reference chain: json.TestClassParent["children"]->java.util.ArrayList[0])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:178)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:88)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:254)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:189)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:130)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1171)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at json.TestClassImportExportTest.test(TestClassImportExportTest.java:18)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
property = "type", defaultImpl = TestClassParent.class)
class TestClassParent {

    private ITestClassChild child;

    /*private Collection<ITestClassChild> children;*/

    public TestClassParent(){
        //child = new TestClassChild();
        /*children = new ArrayList<>();
        children.add(child1);*/
    }

    public ITestClassChild getChild() {
        return child;
    }

    public void setChild(ITestClassChild child) {
        this.child = child;
    }

}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
        property = "type", defaultImpl = ITestClassChild.class)
interface ITestClassChild {
    public String getId();
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
property = "type", defaultImpl = TestClassChild.class)
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, 
property="id")
class TestClassChild implements ITestClassChild {

private String id;

    public TestClassChild(){
    id = "1";
    }

    @Override
    public String getId() {

        return id;
    }
}