ObjectMapper.readValues() 对于错误的 JSON 输入的奇怪行为

问题描述

我正在开发一个经常使用 Jackson 的应用程序。为了了解 readValue() 在某些极端情况下的工作原理,我设置了一个小实验。首先,一个有目的地空的内部类:

static class Empty {
    @Override
    public String toString(){
        return "Empty class!";
    }
}

现在让我们设置一些打印输出

public void testFromJsonStringBadinput() {
    String[] emptyNullOrBadJsons = {"","{}","{","}","}{","{{}","{}}"};
    Class<?>[] types = {Empty.class,Object.class};
    for(String s: emptyNullOrBadJsons) {
        for(Class<?> clazz : types) {
            try {
                    System.out.println("new ObjectMapper().readValue(" + s +  "," + clazz.getSimpleName() + ")=" + new ObjectMapper().readValue(s,clazz));
            } catch(Exception exc) {
                    System.out.println("Deserialization failure for Json string: " + s + " and class: " + clazz.getSimpleName() + ". Exception: " + exc.getClass().getSimpleName() +" and message: " + exc.getMessage());
            }
        }
    }
}

因此,对于一堆边缘情况 JSON,我反序列化为 EmptyObject 的实例,并打印 readValue() 生成的对象。这是这段小代码输出

Deserialization failure for Json string:  and class: Empty. Exception: MismatchedInputException and message: No content to map due to end-of-input
 at [Source: (String)""; line: 1,column: 0]
Deserialization failure for Json string:  and class: Object. Exception: MismatchedInputException and message: No content to map due to end-of-input
 at [Source: (String)""; line: 1,column: 0]
new ObjectMapper().readValue({},Empty)=Empty class!
new ObjectMapper().readValue({},Object)={}
Deserialization failure for Json string: { and class: Empty. Exception: JsonEOFException and message: Unexpected end-of-input: expected close marker for Object (start marker at [Source: (String)"{"; line: 1,column: 1])
 at [Source: (String)"{"; line: 1,column: 2]
Deserialization failure for Json string: { and class: Object. Exception: JsonEOFException and message: Unexpected end-of-input: expected close marker for Object (start marker at [Source: (String)"{"; line: 1,column: 2]
Deserialization failure for Json string: } and class: Empty. Exception: JsonParseException and message: Unexpected close marker '}': expected ']' (for root starting at [Source: (String)"}"; line: 1,column: 0])
 at [Source: (String)"}"; line: 1,column: 2]
Deserialization failure for Json string: } and class: Object. Exception: JsonParseException and message: Unexpected close marker '}': expected ']' (for root starting at [Source: (String)"}"; line: 1,column: 2]
Deserialization failure for Json string: }{ and class: Empty. Exception: JsonParseException and message: Unexpected close marker '}': expected ']' (for root starting at [Source: (String)"}{"; line: 1,column: 0])
 at [Source: (String)"}{"; line: 1,column: 2]
Deserialization failure for Json string: }{ and class: Object. Exception: JsonParseException and message: Unexpected close marker '}': expected ']' (for root starting at [Source: (String)"}{"; line: 1,column: 2]
Deserialization failure for Json string: {{} and class: Empty. Exception: JsonParseException and message: Unexpected character ('{' (code 123)): was expecting double-quote to start field name
 at [Source: (String)"{{}"; line: 1,column: 3]
Deserialization failure for Json string: {{} and class: Object. Exception: JsonParseException and message: Unexpected character ('{' (code 123)): was expecting double-quote to start field name
 at [Source: (String)"{{}"; line: 1,column: 3]
new ObjectMapper().readValue({}},Empty)=Empty class!
new ObjectMapper().readValue({}},Object)={}

Process finished with exit code 0

我希望在所有情况下都能看到此输出除了最后一个字符串 "{}}"。 Jackson 反序列化器似乎很好地解析了这个 JSON,没有抛出异常,这对于我的自定义 Empty 类和 Object 类都是成功的。怎么来的?我本以为 readValue() 会扔在这里

如果它在任何方面很重要,这是我整个 pom.xml 中唯一的 Jackson 参考:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

解决方法

我想我明白了。 Jackson 选择在成功闭合括号对之后不解析 JSON 的任何部分。我将以下字符串添加到我正在处理的错误 JSON 数组中:

ignore

完整方法:

"{}}}","{}}}}}}}}","{ \"obj\":{}}}","{\"name\" : \"Jason\"}}"

输出支持了假设,也反映了public void testFromJsonStringBadInput() { String[] emptyNullOrBadJsons = {"","{}","{","}","}{","{{}","{}}","{}}}","{\"name\" : \"Jason\"}}"}; Class<?>[] types = {Empty.class,Object.class}; for(String s: emptyNullOrBadJsons) { for(Class<?> clazz : types) { try { System.out.println("new ObjectMapper().readValue(" + s + "," + clazz.getSimpleName() + ")=" + new ObjectMapper().readValue(s,clazz)); } catch(Exception exc) { System.out.println("Deserialization failure for Json string: " + s + " and class: " + clazz.getSimpleName() + ". Exception: " + exc.getClass().getSimpleName() +" and message: " + exc.getMessage()); } } } } 不足以解析字符串Empty"{ \"obj\":{}}}"的事实:

 "{\"name\" : \"Jason\"}}"