4. JSON字符串是如何被解析的?JsonParser了解一下(下)

简介: 4. JSON字符串是如何被解析的?JsonParser了解一下(下)

ALLOW_MISSING_VALUES(false)


自2.10版本后,使用JsonReadFeature#ALLOW_MISSING_VALUES代替


是否允许支持JSON数组中“缺失”值。怎么理解:数组中缺失了值表示两个逗号之间,啥都没有,形如这样[value1, , value3]。


@Test
public void test6() throws IOException {
    String jsonStr = "{\"names\" : [\"YourBatman\",,\"A哥\",,] }";
    JsonFactory factory = new JsonFactory();
    try (JsonParser jsonParser = factory.createParser(jsonStr)) {
        // jsonParser.enable(JsonParser.Feature.ALLOW_MISSING_VALUES);
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String fieldname = jsonParser.getCurrentName();
            if ("names".equals(fieldname)) {
                jsonParser.nextToken();
                while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                    System.out.println(jsonParser.getText());
                }
            }
        }
    }
}


运行程序,抛错:

YourBatman // 能输出一个,毕竟第一个part(JsonToken)是正常的嘛
com.fasterxml.jackson.core.JsonParseException: Unexpected character (',' (code 44)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (String)"{"names" : ["YourBatman",,"A哥",,] }"; line: 1, column: 27]


放开注释掉的代码,再次运行,一切正常,结果为:

YourBatman
null
A哥
null
null


请注意:此时数组的长度是5哦。


小贴士:此处用的String类型展示结果,是因为null可以作为String类型(jsonParser.getText()得到null是合法的)。但如果你使用的int类型(或者bool类型),那么如果是null的话就报错喽Current token (VALUE_NULL) not of boolean type,有兴趣的亲可自行尝试,巩固下理解的效果。报错原因文上已有说明~


ALLOW_TRAILING_COMMA(false)


自2.10版本后,使用JsonReadFeature#ALLOW_TRAILING_COMMA代替


是否允许最后一个多余的逗号(一定是最后一个)。这个特征是非常重要的,若开关打开,有如下效果:


  • [true,true,]等价于[true, true]
  • {“a”: true,}等价于{“a”: true}


当这个特征和上面的ALLOW_MISSING_VALUES特征同时使用时,本特征优先级更高。也就是说:会先去除掉最后一个逗号后,再进行数组长度的计算。


举个例子:当然这两个特征开关都打开时,[true,true,]等价于[true, true]好理解;并且呢,[true,true,,]是等价于[true, true, null]的哦,可千万别忽略最后的这个null。


@Test
public void test7() throws IOException {
    String jsonStr = "{\"results\" : [true,true,,] }";
    JsonFactory factory = new JsonFactory();
    try (JsonParser jsonParser = factory.createParser(jsonStr)) {
        jsonParser.enable(JsonParser.Feature.ALLOW_MISSING_VALUES);
        // jsonParser.enable(JsonParser.Feature.ALLOW_TRAILING_COMMA);
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String fieldname = jsonParser.getCurrentName();
            if ("results".equals(fieldname)) {
                jsonParser.nextToken();
                while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                    System.out.println(jsonParser.getBooleanValue());
                }
            }
        }
    }
}


运行程序,输出:


YourBatman
null
A哥
null
null


这完全就是上例的效果嘛。现在我放开注释掉的代码,再次运行,结果为:


YourBatman
null
A哥
null


请注意对比前后的结果差异,并自己能能自己合理解释。


校验相关

Jackson在JSON标准之外,给出了两个校验相关的特征。


STRICT_DUPLICATE_DETECTION(false)


自2.10版本后,使用StreamReadFeature#STRICT_DUPLICATE_DETECTION代替


是否允许JSON串有两个相同的属性key,默认是允许的。


@Test
public void test8() throws IOException {
    String jsonStr = "{\"age\":18, \"age\": 28 }";
    JsonFactory factory = new JsonFactory();
    try (JsonParser jsonParser = factory.createParser(jsonStr)) {
        // jsonParser.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String fieldname = jsonParser.getCurrentName();
            if ("age".equals(fieldname)) {
                jsonParser.nextToken();
                System.out.println(jsonParser.getIntValue());
            }
        }
    }
}


运行程序,正常输出:

18
28



若放开注释代码,再次运行,则抛错:

18 // 第一个数字还是能正常输出的哟
com.fasterxml.jackson.core.JsonParseException: Duplicate field 'age'
 at [Source: (String)"{"age":18, "age": 28 }"; line: 1, column: 17]

GNORE_UNDEFINED(false)


自2.10版本后,使用StreamReadFeature#IGNORE_UNDEFINED代替


是否忽略没有定义的属性key。和JsonGenerator.Feature#IGNORE_UNKNOWN的这个特征一样,它作用于预先定义了格式的数据类型,如Avro、protobuf等等,JSON是不需要预先定义的哦~


同样的,你可以通过这个API预先设置格式:

JsonParser:
    public void setSchema(FormatSchema schema) {
      ...
    }


其它


INCLUDE_SOURCE_IN_LOCATION(true)


自2.10版本后,使用StreamReadFeature#INCLUDE_SOURCE_IN_LOCATION代替


是否构建JsonLocation对象来表示每个part的来源,你可以通过JsonParser#getCurrentLocation()来访问。作用不大,就此略过。


总结


本文介绍了底层流式API JsonParser读JSON的方式,它不仅仅能够处理标准JSON,也能通过Feature特征值来控制,开启对一些非标准但又比较常用的JSON串的支持,这不正式一个优秀框架/库应有的态度麽:兼容性。


结合上篇文章对写JSON时JsonGenerator的描述,能够总结出两点原则:


  • 写:100%遵循规范
  • 读:最大程度兼容并包


写代表你的输出,遵循规范的输出能确保第三方在用你输出的数据时不至于对你破口大骂,所以这是你应该做好的本分。读代表你的输入,能够处理规范的格式是你的职责,但我若还能额外的处理一些非标准格式(一般为常用的),那绝对是闪耀点,也就是你给的情分。本分是你应该做的,而情分就是你的加分项。



相关文章
|
2月前
|
JSON JavaScript 前端开发
C++ 智能指针与 JSON 处理:高级编程技巧与常见问题解析
C++ 智能指针与 JSON 处理:高级编程技巧与常见问题解析
271 0
|
1天前
|
存储 JSON DataWorks
DataWorks产品使用合集之DataWorks将 MongoDB 中的数组类型写入到 DataWorks 的单个字段时,表示为字符串格式而非 JSON 格式如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
8 3
|
1天前
|
JSON 分布式计算 大数据
MaxCompute产品使用合集之大数据计算MaxCompute 要提取JSON字符串中的所有key-value对,我该怎么操作
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
5天前
|
存储 NoSQL 安全
Redis入门到通关之数据结构解析-动态字符串SDS
Redis入门到通关之数据结构解析-动态字符串SDS
12 0
|
9天前
|
JSON 运维 Kubernetes
云效产品使用报错问题之流水线中配置了AppStack,构建时下载的制品内容为json字符串,如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
18天前
|
存储 JSON JavaScript
「Python系列」Python JSON数据解析
在Python中解析JSON数据通常使用`json`模块。`json`模块提供了将JSON格式的数据转换为Python对象(如列表、字典等)以及将Python对象转换为JSON格式的数据的方法。
33 0
|
28天前
|
JSON 数据格式
Json字符串与QVariantList 对象相互转换
Json字符串与QVariantList 对象相互转换
7 0
|
5天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
13天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
44 0
|
13天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
43 0

推荐镜像

更多