反序列化导致不匹配InputException:泛型类型接口的意外标记(值\字符串)

wfauudbj  于 2021-08-20  发布在  Java
关注(0)|答案(0)|浏览(384)

我在编写一个测试时遇到了一个问题,该测试首先使用jackson将对象序列化为字符串,然后使用json将其反序列化。我试图根据实际问题创建一个mwe。
底层代码使用jaxb注解,必要时添加jackson注解。对于本身是接口的泛型属性,会出现此问题。在mwe中有一个类 Model 具有泛型属性 value 类型 ValueInterface . value 它本身被用作 @XmlIDREF 在…内 Model . 在底层工具中,我使用 Memory 储存 Model s和 Value s独立用于重用,作为多个 Model 示例可以使用相同的方法 Value 对象
我得到的是:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_STRING), expected START_OBJECT: need JSON Object to contain As.WRAPPER_OBJECT type information for class org.raedma.jacksonjsondeserializationquestion.ValueInterface

Jackson似乎无法解决这个问题 XmlIDREF 字符串,但希望 value 作为一个新节点。我已经尝试了不同的解决方法,例如这里和这里,告诉jackson这是对具有 @XmlID . 不幸的是,没有任何帮助。
有什么想法吗?
我应该提到,在底层代码中, Value 它本身是某些超类的子类型。差不多 @JsonDeserialize(as = MyInterfaceImpl.class) 这里提到的是不可能的,否则我就不需要接口了。同样的方法也适用于jaxbforxml。

mwe Main :

public class Main{

     public static void main(String[] args) throws JsonProcessingException, JAXBException{

         Value value = new Value("valueID",1);
         Collection<Value> values = new ArrayList<>();
         values.add(value);

         Model<Value> model = new Model<>("modelID", value);
         Collection<Model> models = new ArrayList<>();
         models.add(model);

         Memory memory = new Memory();
         memory.setValues(values);
         memory.setModels(models);

         //
         json(memory);

         //
         //xml(memory);

     }

     private static void json(Memory memory) throws JsonProcessingException{

         // Serialize
         ObjectMapper outObjectMapper = new ObjectMapper();
         outObjectMapper.registerModule(new JaxbAnnotationModule());
         outObjectMapper.enable(SerializationFeature.INDENT_OUTPUT);
         outObjectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
         outObjectMapper.setSerializationInclusion(Include.NON_NULL);

         DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
         prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
         outObjectMapper.setDefaultPrettyPrinter(prettyPrinter);
         String result = outObjectMapper.writeValueAsString(memory);
         //System.out.println(result);

         // Deserialize
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
         objectMapper.registerModule(new JaxbAnnotationModule());
         Memory deserial = objectMapper.readValue(result, Memory.class);

     }

     private static void xml(Memory memory) throws PropertyException, JAXBException{

         // Creating the Document object
         StringWriter document = new StringWriter();

         // create JAXB context
         JAXBContext context = JAXBContext.newInstance(memory.getClass());

         //Marshaller marshaller = context.createMarshaller();
         Marshaller marshaller = context.createMarshaller();
         marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
         // Marshaling the User object into a Document object
         marshaller.marshal(memory, document);

         //
         String result = document.toString();

         //System.out.println(result);
     }

 }
``` `Value.class` :

@EqualsAndHashCode

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)

public class Value
implements
ValueInterface
{

 @XmlID
 @XmlAttribute
 private String name;

 private int attribute;

 public Value() {}

 public Value(
         String name
        ,int attribute
 ) {
     this.name = name;
     this.attribute = attribute;
 }

 public String getName() {return name;}
 public void setName(String name) {this.name = name;}

 public int getAttribute() {return attribute;}
 public void setAttribute(int attribute) {this.attribute = attribute;}

}
``` ValueInterface :

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
 @JsonSubTypes({
     @JsonSubTypes.Type(value = Value.class)
 })
 public interface ValueInterface<
             T extends ValueInterface<T>
         >
 {

 }
``` `Model` :

@EqualsAndHashCode

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)

public class Model<
V extends ValueInterface
>
{

 @XmlID
 @XmlAttribute
 private String name;

 @XmlIDREF
 @XmlElements({
     @XmlElement(type=Value.class)
 })
 private V value;

 public Model() {}

 public Model(String name, V value) {
     this.name = name;
     this.value = value;
 }

 public String getName() {return name;}
 public void setName(String name) {this.name = name;}

 public V getValue() {return value;}
 public void setValue(V value) {this.value = value;}

}
``` Memory :

@EqualsAndHashCode

 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)

 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)

 public class Memory{

     @XmlElementWrapper(name="models")
     @XmlElement(type=Model.class, name="mode")
     private Collection<Model> models;

     @XmlElementWrapper(name="values")
     @XmlElement(type=Value.class, name="value")
     private Collection<Value> values;

     public void setModels(Collection<Model> v){this.models = v;}
     public Collection<Model> getModels(){return models;}

     public void setValues(Collection<Value> v){this.values = v;}
     public Collection<Value> getValues(){return values;}

 }
``` `POM.xml` :
 <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <maven.compiler.source>13</maven.compiler.source>
     <maven.compiler.target>13</maven.compiler.target>
     <!-- JAXB -->
     <javax.xml.bind.jaxb-api.version>2.4.0-b180830.0359</javax.xml.bind.jaxb-api.version>
     <javax.activation.activation.version>1.1.1</javax.activation.activation.version>
     <org.glassfish.jaxb.jaxb-runtime.version>3.0.2-b01</org.glassfish.jaxb.jaxb-runtime.version>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.18.18</version>
         <type>jar</type>
     </dependency>
     <dependency>
         <groupId>org.junit.jupiter</groupId>
         <artifactId>junit-jupiter-api</artifactId>
         <version>5.6.0</version>
         <scope>test</scope>
     </dependency>
     <dependency>
         <groupId>org.junit.jupiter</groupId>
         <artifactId>junit-jupiter-params</artifactId>
         <version>5.6.0</version>
         <scope>test</scope>
     </dependency>
     <dependency>
         <groupId>org.junit.jupiter</groupId>
         <artifactId>junit-jupiter-engine</artifactId>
         <version>5.6.0</version>
         <scope>test</scope>
     </dependency>
     <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
         <version>2.12.3</version>
         <type>jar</type>
     </dependency>
     <dependency>
         <groupId>com.fasterxml.jackson.module</groupId>
         <artifactId>jackson-module-jaxb-annotations</artifactId>
         <version>2.12.3</version>
         <type>jar</type>
     </dependency>
     <!-- JAXB -->
     <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
         <version>2.3.0</version>
     </dependency>
     <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-core</artifactId>
         <version>2.3.0</version>
     </dependency>
     <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <version>2.3.0</version>
     </dependency>
 </dependencies>

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题