I'm new to Java, and I'm wondering how to deserialize an empty JSON array into an empty Java object of type TreeMap<String, MyOtherClass>.
Currently, I'm attempting to deserialize a JSON file with an array of objects, and each object into a class called MyClass. The class is roughly as follows:
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyClass {
private final String propertyOne;
private final String propertyTwo;
private final String propertyThree;
@JsonSerialize(contentAs = MyOtherClass.class)
@JsonDeserialize(contentAs = MyOtherClass.class)
TreeMap<String, MyOtherClass> otherThings = new TreeMap<>();
@JsonCreator
public MyClass(
@JsonProperty("propertyOne") String propertyOne,
@JsonProperty("propertyTwo") String propertyTwo,
@JsonProperty("propertyThree") String propertyThree) {
this.propertyOne = propertyOne;
this.propertyTwo = propertyTwo;
this.propertyThree = propertyThree;
// Getters and setters below
@JsonSetter("otherThings")
public void setOtherThings() {
if (this.otherThings == null || this.otherThings.isEmpty()) {
this.otherThings = new TreeMap<>();
}
}
}
}
One of the entries in the original JSON is this field otherThings. I've represented this entry using MyOtherClass, which handles the properties that otherThings could contain.
Currently, this works perfect for serialization, and for deserialization when otherThings is populated. However, when I have something like the following:
{
"propertyOne": "This is propertyOne!",
"propertyTwo": "This is propertyTwo!",
"propertyThree": "This is propertyThree!",
"otherThings": []
}
I get the following stack trace:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.TreeMap<java.lang.String,org.something.model.MyOtherClass>` from Array value (token `JsonToken.START_ARRAY`)
at [Source: (URL); line: 7, column: 14] (through reference chain: java.util.ArrayList[0]->org.something.model.Order["lines"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1741)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1515)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromArray(StdDeserializer.java:222)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:447)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:277)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:462)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:351)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:184)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:355)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3572)
at org.something.model.MyClass.populateMyClassFromJson(MyClass.java:148)
at org.something.service.MyClassService.displayMyClassObject(MyClassService.java:96)
at Main.main(Main.java:9)
I've tried:
- Using
ObjectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT), but that doesn't really help sinceotherThingsgets instantiated asnull. - Using the
JsonSetterforsetOtherThingsyou see above. This has to be careful because I don't want to overwriteotherThingsif it already contains things inside of it.
EDIT: Here's also the method populateMyClassFromJson if it helps:
public void populateMyClassFromJson() throws IOException {
List<MyClass> myClassList = mapper.readValue(new File("/path/to/my_classes.json"), new TypeReference<>() {});
Map<String, MyClass> myClassMap = myClassList.stream().collect(Collectors.toMap(MyClass::getId, Function.identity()));
myClassTreeMap.putAll(myClassMap);
}