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

的一个很好的教程