将空 JSON 数组反序列化为空 TreeMap
Deserialize empty JSON array into empty TreeMap
我是 Java 的新手,我想知道如何将一个空 JSON 数组反序列化为一个 TreeMap<String, MyOtherClass>
类型的空 Java 对象。
目前,我正在尝试反序列化一个包含对象数组的 JSON 文件,并将每个对象反序列化为一个名为 MyClass
的 class。 class大致如下:
@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<>();
}
}
}
}
原始 JSON 中的条目之一是此字段 otherThings
。我使用 MyOtherClass
表示此条目,它处理 otherThings
可能包含的属性。
目前,这非常适合 序列化 ,以及填充 otherThings
时的反序列化。但是,当我遇到以下情况时:
{
"propertyOne": "This is propertyOne!",
"propertyTwo": "This is propertyTwo!",
"propertyThree": "This is propertyThree!",
"otherThings": []
}
我得到以下堆栈跟踪:
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)
我试过:
- 使用
ObjectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)
,但这并没有真正帮助,因为 otherThings
被实例化为 null
。
- 将
JsonSetter
用于 setOtherThings
,如上所示。这必须小心,因为我不想覆盖 otherThings
如果它里面已经包含了东西。
编辑:如果有帮助,这也是方法populateMyClassFromJson
:
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);
}
总结一下(我相信从一开始就很清楚):如错误所述,问题是 Jackson 试图将字段反序列化为 TreeMap,这不会起作用,因为在 JSON 中有一个数组 []
.
不过我觉得你的 setter 有点奇怪。我相信你应该有这样的东西(根据你的评论和更新更新):
@JsonSetter("otherThings")
public void setOtherThings(MyOtherClass[] arr) {
this.otherThings = List.of(Optional.ofNullable(arr)
.orElse(new MyOtherClass[0])).stream()
.collect(Collectors.toMap(MyOtherClass::getId, Function.identity(),
(o1, o2) -> o1, TreeMap::new));
}
当然你也要处理数组不为空的情况
我是 Java 的新手,我想知道如何将一个空 JSON 数组反序列化为一个 TreeMap<String, MyOtherClass>
类型的空 Java 对象。
目前,我正在尝试反序列化一个包含对象数组的 JSON 文件,并将每个对象反序列化为一个名为 MyClass
的 class。 class大致如下:
@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<>();
}
}
}
}
原始 JSON 中的条目之一是此字段 otherThings
。我使用 MyOtherClass
表示此条目,它处理 otherThings
可能包含的属性。
目前,这非常适合 序列化 ,以及填充 otherThings
时的反序列化。但是,当我遇到以下情况时:
{
"propertyOne": "This is propertyOne!",
"propertyTwo": "This is propertyTwo!",
"propertyThree": "This is propertyThree!",
"otherThings": []
}
我得到以下堆栈跟踪:
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)
我试过:
- 使用
ObjectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)
,但这并没有真正帮助,因为otherThings
被实例化为null
。 - 将
JsonSetter
用于setOtherThings
,如上所示。这必须小心,因为我不想覆盖otherThings
如果它里面已经包含了东西。
编辑:如果有帮助,这也是方法populateMyClassFromJson
:
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);
}
总结一下(我相信从一开始就很清楚):如错误所述,问题是 Jackson 试图将字段反序列化为 TreeMap,这不会起作用,因为在 JSON 中有一个数组 []
.
不过我觉得你的 setter 有点奇怪。我相信你应该有这样的东西(根据你的评论和更新更新):
@JsonSetter("otherThings")
public void setOtherThings(MyOtherClass[] arr) {
this.otherThings = List.of(Optional.ofNullable(arr)
.orElse(new MyOtherClass[0])).stream()
.collect(Collectors.toMap(MyOtherClass::getId, Function.identity(),
(o1, o2) -> o1, TreeMap::new));
}
当然你也要处理数组不为空的情况