java - Jackson 的 JSON (2.5.0) 验证未按预期工作

标签 java json jackson

简单的测试用例:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public static void main(String[] args) throws Exception {
    String json = "1,2";
    ObjectMapper parser = new ObjectMapper();
    JsonNode rootNode = parser.readTree(json);

}

抛出异常:

Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: 
Unexpected character (',' (code 44)): Expected space separating root-level values
at [Source: 1,2; line: 1, column: 3]

一切都很好,但如果我将 String json 更改为以下任何一项:

String json = "null,false";
String json = "[1,2,3,null,\"hello\"],false";
String json = "true,3";
String json = "true,{\"test\":3}";

没有异常抛出。

为什么会出现差异?

最佳答案

默认情况下,Jackson 使用ReaderBasedJsonParser,其中,在读取/初始化要解析的 JSON 时,有一个显式检查

switch (i) {
        case '"':
            _tokenIncomplete = true;
            t = JsonToken.VALUE_STRING;
            break;
        case '[':
            if (!inObject) {
                _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol);
            }
            t = JsonToken.START_ARRAY;
            break;
        case '{':
            if (!inObject) {
                _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol);
            }
            t = JsonToken.START_OBJECT;
            break;
        case ']':
        case '}':
            // Error: neither is valid at this point; valid closers have
            // been handled earlier
            _reportUnexpectedChar(i, "expected a value");
        case 't':
            _matchTrue();
            t = JsonToken.VALUE_TRUE;
            break;
        case 'f':
            _matchFalse();
            t = JsonToken.VALUE_FALSE;
            break;
        case 'n':
            _matchNull();
            t = JsonToken.VALUE_NULL;
            break;

        case '-':
            /* Should we have separate handling for plus? Although
             * it is not allowed per se, it may be erroneously used,
             * and could be indicate by a more specific error message.
             */
            t = _parseNegNumber();
            break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            t = _parsePosNumber(i);
            break;

从上面的代码中,您可以看到它会检查您提到的字符 - null、true、{、[、false 等。如果有任何匹配,它会返回有效的 json 标记。这就是为什么,如果你改变

String json = "true,3";

String json = "3,true";

它会再次抛出众所周知的异常。

请注意,还会检查以字母“n”开头的给定字符串,验证它是否与 null 匹配(对以“t”、“f”开头的字符串进行相同检查)。

然后有趣的是 _parsePosNumber(i) 方法,它基本上调用 _reportMissingRootWS 来检查根 - 但它显然失败了。

所以基本上,如果 json 是有效的,它永远不会达到“失败者”的情况,或者如果给定的字符串以“true”、“false”、“null”、“[”、“{”、“]”中的一个开头, "}"它也将被视为有效的 json。

我假设此功能在 Jackson non standard features 的列表中,因此上述格式被视为有效的 JSON。

关于java - Jackson 的 JSON (2.5.0) 验证未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28632365/

相关文章:

json - 核心数据和JSON问题

java - 如何在 Jackson 的自定义反序列化器中委托(delegate)默认反序列化?

java - 解码 Json 对象时出现 "Content is not allowed in prolog"

java - 如何使用 Liquibase 创建数据库

java - 如何在 fragment 中使用方法?

java - 如何从遵循特定格式的字符串中删除未知字符?

rest - Spring Boot REST 服务 : JSON Deserialization Not Working

java - SparkJava Web浏览器下载html文件而不是在部署war文件时显示

android - 无法使用用户名和密码获取 HTTP Post 请求的 JSON 数据?

javascript - 使用 D3 从休息服务获取数据