Reputation: 60184
I have a JSON:
{
"firstField": "Something One",
"secondField": "Something Two",
"thirdField": [
{
"thirdField_one": "Something Four",
"thirdField_two": "Something Five"
},
{
"thirdField_one": "Something Six",
"thirdField_two": "Something Seven"
}
],
"fifthField": [
{
"fifthField_one": "Something… ",
"fifthField_two": "Something...",
"fifthField_three": 12345
},
{
"fifthField_one": "Something",
"fifthField_two": "Something",
"fifthField_three": 12345
}
]
}
I have my classes:
public static class MyClass {
@JsonProperty
private String firstField, secondField;
@JsonProperty
private ThirdField thirdField;
@JsonProperty
private FifthField fifthField;
public static class ThirdField {
private List<ThirdFieldItem> thirdField;
}
public static class ThirdFieldItem {
private String thirdField_one, thirdField_two;
}
public static class FifthField {
private List<FifthFieldItem> fifthField;
}
public static class FifthFieldItem {
private String fifthField_one, fifthField_two;
private int fifthField_three;
}
}
I'm deserializing them with Jackson library:
public void testJackson() throws IOException {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
File from = new File("text.txt"); // JSON I mentioned above
mapper.readValue(from, MyClass.class);
}
but I'm getting the Exception:
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of Main$MyClass$ThirdField out of START_ARRAY token
Upvotes: 2
Views: 2711
Reputation: 148977
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Since it is not always possible to change your domain model (as answered by @Perception), below is how you could map your original object model to the desired JSON using MOXy.
Java Model
In this use case you can leverage the @XmlPath(".")
extension. This tells MOXy to bring the contents of the target object into the sources node.
@XmlAccessorType(XmlAccessType.FIELD)
public static class MyClass {
private String firstField, secondField;
@XmlPath(".")
private ThirdField thirdField;
@XmlPath(".")
private FifthField fifthField;
@XmlAccessorType(XmlAccessType.FIELD)
public static class ThirdField {
private List<ThirdFieldItem> thirdField;
}
@XmlAccessorType(XmlAccessType.FIELD)
public static class ThirdFieldItem {
private String thirdField_one, thirdField_two;
}
@XmlAccessorType(XmlAccessType.FIELD)
public static class FifthField {
private List<FifthFieldItem> fifthField;
}
@XmlAccessorType(XmlAccessType.FIELD)
public static class FifthFieldItem {
private String fifthField_one, fifthField_two;
private int fifthField_three;
}
}
Conversion Code
The demo code below shows how to enable MOXy's JSON binding.
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(2);
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {MyClass.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource("src/forum13600952/input.json");
MyClass myClass = unmarshaller.unmarshal(json, MyClass.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(myClass, System.out);
}
input.json/Output
Belos is the input from your question slightly reformatted to match the output produced by MOXy.
{
"firstField" : "Something One",
"secondField" : "Something Two",
"thirdField" : [ {
"thirdField_one" : "Something Four",
"thirdField_two" : "Something Five"
}, {
"thirdField_one" : "Something Six",
"thirdField_two" : "Something Seven"
} ],
"fifthField" : [ {
"fifthField_one" : "Something...",
"fifthField_two" : "Something...",
"fifthField_three" : 12345
}, {
"fifthField_one" : "Something",
"fifthField_two" : "Something",
"fifthField_three" : 12345
} ]
}
For More Information
Upvotes: 0
Reputation: 80593
You defined your thirdField
and fifthField
properties as arrays in your JSON. They need to be arrays or collections on your Java bean as well:
public static class MyClass {
@JsonProperty
private String firstField, secondField;
@JsonProperty
private Collection<ThirdField> thirdField;
@JsonProperty
private Collection<FifthField> fifthField;
/// ...
}
As you are going through and converting an existing JSON object into beans, keep in mind that JSON data is very much like a map. If you envision how you would map the data from a map into your object it really helps. Your ThirdField
and FifthField
objects need to map the definitions in your JSON. This is what your JSON says a ThirdField
is:
{
"thirdField_one": "Something Four",
"thirdField_two": "Something Five"
}
Literally converting that to a Java bean gives you:
public class ThirdField implements Serializable {
private String thirdField_one;
private String thirdField_two;
// ...
}
You can add in your annotations etc, etc to get a full fledged bean. Do the same thing for your FifthField
object.
Upvotes: 5