Hello,
I have a simple XSD file. From that file, we generate Java Objects using
XJC. We want to serialize and deserialize such objects to XML (which
worked) and to JSON. A valid XML looks like this:
<user>
<loginId>demo</loginId>
<roles>
<role>ADMIN</role>
<role>USER</role>
</roles></user>
If we use Jackson (version 2.9.0) to generate a JSON String out of the
JAX-B class, without any Mixin Configuration, it will look like this:
{
"loginId": "demo",
"roles": {
"role": ["ADMIN","USER"]
}}
To avoid the "roles"/"role" construct, we use a Mixin to get the following
result:
{
"loginId": "demo",
"roles": ["ADMIN", "USER"]}
This worked for the serialization process, but not for deserialization.
Here is the code, we use to configure the Mapper and to test the
deserialization:
public class JSONSupportTest {
private static final String USER_JSON = "{\n"
+ " \"loginId\": \"demo\",\n"
+ " \"roles\": [\n"
+ " \"ADMIN\",\n"
+ " \"USER\"\n"
+ " ]\n"
+ "}";
@Test
public void testJSONDeserialization() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.addMixIn(JAXBElement.class, JaxBElementMixin.class);
mapper.addMixIn(Roles.class, UserRolesMixin.class); // this line avoids
the "roles"/"role" construct
UserType result = mapper.readValue(USER_JSON, UserType.class);
System.out.println(result);
}}
With that code, we run in the following exception:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize
instance of de.demo.UserType$Roles out of START_ARRAY token
at [Source: (String)"{
"loginId": "demo",
"roles": [
"ADMIN",
"USER"
]
}"; line: 3, column: 14] (through reference chain: de.demo.UserType["roles"])
at
com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at
com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1329)
at
com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1138)
at
com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1092)
at
com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1439)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:185)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at
com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
at de.demo.JSONSupportTest.testJSONDeserialization(JSONSupportTest.java:22)
Is there a way, that Jackson supports both ways (serialization and
deserialization)?
Here is the full code:
*The XSD File:*
<schema xmlns:tns="http://demo.de" elementFormDefault="qualified"
targetNamespace="http://demo.de" version="2.0"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="user" type="tns:UserType"/>
<complexType name="UserType">
<sequence>
<element minOccurs="1" maxOccurs="1" name="loginId" type="string" />
<element maxOccurs="1" minOccurs="1" name="roles">
<complexType>
<sequence>
<element maxOccurs="unbounded" minOccurs="1" name="role"
type="tns:RoleType" />
</sequence>
</complexType>
</element>
</sequence></complexType>
<simpleType name="RoleType">
<restriction base="string">
<enumeration value="USER" />
<enumeration value="ADMIN" />
</restriction></simpleType>
*The JAX-B Classes generated by XJC:*
@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "UserType", propOrder = {
"loginId",
"roles"})public class UserType {
@XmlElement(required = true)
protected String loginId;
@XmlElement(required = true)
protected UserType.Roles roles;
public String getLoginId() {
return loginId;
}
public void setLoginId(String value) {
this.loginId = value;
}
public UserType.Roles getRoles() {
return roles;
}
public void setRoles(UserType.Roles value) {
this.roles = value;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"role"
})
public static class Roles {
@XmlElement(required = true)
@XmlSchemaType(name = "string")
protected List<RoleType> role;
public List<RoleType> getRole() {
if (role == null) {
role = new ArrayList<RoleType>();
}
return this.role;
}
}}
@XmlType(name = "RoleType")@XmlEnumpublic enum RoleType {
USER,
ADMIN;
public String value() {
return name();
}
public static RoleType fromValue(String v) {
return valueOf(v);
}}
*And finally the Mixin class for the roles part*
public class UserRolesMixin extends Roles{
@JsonValue
@Override
public List<RoleType> getRole() {
return super.getRole();
}}
I have not find out what is wrong with the code. Why does it only work in the
serialization case and not in deserialization?
Thanks a lot
--
You received this message because you are subscribed to the Google Groups
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.