我在编写一个测试时遇到了一个问题,该测试首先使用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>
暂无答案!
目前还没有任何答案,快来回答吧!