Jackson 数组反序列化为 java:MismatchedInputException:尝试读取类型值时出现意外的输入结束
Jackson array deserialize to java: MismatchedInputException: Unexpected end-of-input when trying read value of type
描述
我正在尝试将 json 数组字符串解析为 java 集合,并且我已经检查了数组字符串的格式。这是我的测试用例:
List<PropertySchema> schemas = new ArrayList<>();
schemas.add(new PropertySchema("test1", "test1", new BoolDataType(), null, null));
schemas.add(new PropertySchema("test2", "test2", new LongDataType(), null, null));
schemas.add(new PropertySchema("test3","test3",new DoubleDataType(),null,null));
schemas.add(new PropertySchema("test4","test4",new TextDataType(),null,null));
final String js = new ObjectMapper().writeValueAsString(schemas);
System.out.println(js);
schemas = new ObjectMapper().readValue(js, new TypeReference<List<PropertySchema>>() {
});
System.out.println(schemas);
writeValueAsString
成功但 readValue
抛出异常:
异常
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected end-of-input when trying read value of type `com.cainiao.iot.digital.map.bean.PropertySchema`
at [Source: (String)"[{"code":"test1","name":"test1","dataType":{"type":"Boolean"},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test2","name":"test2","dataType":{"type":"Long","unit":null},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test3","name":"test3","dataType":{"type":"Double","unit":null},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test4","name":"test4","dataType":{"type":"String"},"description":null,"ui":null,"defaultV"[truncated 28 chars]; line: 1, column: 528] (through reference chain: java.util.ArrayList[1])
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.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1462)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:223)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:186)
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:4674)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3612)
at com.cainiao.JacksonTest.listDeserialize(JacksonTest.java:89)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access0(ParentRunner.java:66)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
我不明白为什么,有 java bean class:
代码
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class PropertySchema implements Serializable {
private static final long serialVersionUID = 4534224437154640700L;
private String code;
private String name;
@JsonDeserialize(using = TypeDeserializer.class)
private DataType dataType;
private String description;
private String ui;
private Object defaultValue = "";
private boolean editable = true;
public PropertySchema() {
}
public PropertySchema(String code, String name, DataType dataType, Object defaultValue, String description) {
this.code = code;
this.name = name;
this.dataType = dataType;
this.description = description;
this.defaultValue = defaultValue;
}
}
public class TypeDeserializer extends JsonDeserializer<DataType> {
@Override
public DataType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String type = null;
String unit = null;
while (!jsonParser.isClosed()) {
final JsonToken jsonToken = jsonParser.nextToken();
if (JsonToken.FIELD_NAME == jsonToken) {
final String fieldName = jsonParser.currentName();
jsonParser.nextToken();
switch (fieldName) {
case "type":
type = jsonParser.getValueAsString();
break;
case "unit":
unit = jsonParser.getValueAsString();
break;
default:
}
}
}
if (type == null) {
return null;
}
DataType dataType;
switch (type) {
case "Double": {
dataType = new DoubleDataType();
if (unit != null) {
((DoubleDataType) dataType).setUnit(unit);
}
break;
}
case "Boolean": {
dataType = new BoolDataType();
break;
}
case "Long": {
dataType = new LongDataType();
if (unit != null) {
((LongDataType) dataType).setUnit(unit);
}
break;
}
case "String": {
dataType = new TextDataType();
break;
}
default:
return null;
}
return dataType;
}
}
将数组字符串反序列化为 java 集合的正确方法是什么?
问题不在于反序列化集合。我认为 TypeDeserializer
中的 while
循环无法正常工作。它似乎在第一次使用时耗尽了整个对象。与其自己循环对象,不如反序列化 DataType
:
JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
String type = jsonNode.get("type").asText();
String unit = jsonNode.get("unit").asText(); // I'm assuming the type and unit fields are Strings.
反序列化器的其余部分可以基本保持不变。这是关于 using custom deserialization in Jackson
的一个很好的教程
描述
我正在尝试将 json 数组字符串解析为 java 集合,并且我已经检查了数组字符串的格式。这是我的测试用例:
List<PropertySchema> schemas = new ArrayList<>();
schemas.add(new PropertySchema("test1", "test1", new BoolDataType(), null, null));
schemas.add(new PropertySchema("test2", "test2", new LongDataType(), null, null));
schemas.add(new PropertySchema("test3","test3",new DoubleDataType(),null,null));
schemas.add(new PropertySchema("test4","test4",new TextDataType(),null,null));
final String js = new ObjectMapper().writeValueAsString(schemas);
System.out.println(js);
schemas = new ObjectMapper().readValue(js, new TypeReference<List<PropertySchema>>() {
});
System.out.println(schemas);
writeValueAsString
成功但 readValue
抛出异常:
异常
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected end-of-input when trying read value of type `com.cainiao.iot.digital.map.bean.PropertySchema`
at [Source: (String)"[{"code":"test1","name":"test1","dataType":{"type":"Boolean"},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test2","name":"test2","dataType":{"type":"Long","unit":null},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test3","name":"test3","dataType":{"type":"Double","unit":null},"description":null,"ui":null,"defaultValue":null,"editable":true},{"code":"test4","name":"test4","dataType":{"type":"String"},"description":null,"ui":null,"defaultV"[truncated 28 chars]; line: 1, column: 528] (through reference chain: java.util.ArrayList[1])
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.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1462)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:223)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:186)
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:4674)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3612)
at com.cainiao.JacksonTest.listDeserialize(JacksonTest.java:89)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access0(ParentRunner.java:66)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
我不明白为什么,有 java bean class:
代码
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class PropertySchema implements Serializable {
private static final long serialVersionUID = 4534224437154640700L;
private String code;
private String name;
@JsonDeserialize(using = TypeDeserializer.class)
private DataType dataType;
private String description;
private String ui;
private Object defaultValue = "";
private boolean editable = true;
public PropertySchema() {
}
public PropertySchema(String code, String name, DataType dataType, Object defaultValue, String description) {
this.code = code;
this.name = name;
this.dataType = dataType;
this.description = description;
this.defaultValue = defaultValue;
}
}
public class TypeDeserializer extends JsonDeserializer<DataType> {
@Override
public DataType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String type = null;
String unit = null;
while (!jsonParser.isClosed()) {
final JsonToken jsonToken = jsonParser.nextToken();
if (JsonToken.FIELD_NAME == jsonToken) {
final String fieldName = jsonParser.currentName();
jsonParser.nextToken();
switch (fieldName) {
case "type":
type = jsonParser.getValueAsString();
break;
case "unit":
unit = jsonParser.getValueAsString();
break;
default:
}
}
}
if (type == null) {
return null;
}
DataType dataType;
switch (type) {
case "Double": {
dataType = new DoubleDataType();
if (unit != null) {
((DoubleDataType) dataType).setUnit(unit);
}
break;
}
case "Boolean": {
dataType = new BoolDataType();
break;
}
case "Long": {
dataType = new LongDataType();
if (unit != null) {
((LongDataType) dataType).setUnit(unit);
}
break;
}
case "String": {
dataType = new TextDataType();
break;
}
default:
return null;
}
return dataType;
}
}
将数组字符串反序列化为 java 集合的正确方法是什么?
问题不在于反序列化集合。我认为 TypeDeserializer
中的 while
循环无法正常工作。它似乎在第一次使用时耗尽了整个对象。与其自己循环对象,不如反序列化 DataType
:
JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
String type = jsonNode.get("type").asText();
String unit = jsonNode.get("unit").asText(); // I'm assuming the type and unit fields are Strings.
反序列化器的其余部分可以基本保持不变。这是关于 using custom deserialization in Jackson
的一个很好的教程