20221115 JsonFactory、JsonParser、JsonGenerator
参考资料
概述
JsonParser
、JsonGenerator
、JsonFactory
位于 jackson-core
模块中,此模块提供了最具底层的 Streaming JSON 解析器/生成器,这组流式 API 属于Low-Level API ,是 ObjectMapper
的底层实现
-
JsonFactory
:Jackson 主要的工厂方法,用于配置和构建解析器 JsonParser 和生成器 JsonGenerator ,这个工厂实例是线程安全的,所以可以重复使用 -
JsonGenerator
:用来生成 Json 格式的内容的(序列化) -
JsonParser
:读取 Json 格式的内容(反序列化)
相关概念
-
流式(Streaming):此概念和 Java 8 中的 Stream 流是不同的。这里指的是 IO流 ,因此在读/写的最后都是需要 close
-
增量模式(incremental mode):它表示每个部分一个一个地往上增加,类似于垒砖。使用此流式 API 读写 JSON 的方式使用的均是增量模式
-
JsonToken:每一部分都是一个独立的 Token(有不同类型的Token),最终被“拼凑”起来就是一个JSON。这是流式API里很重要的一个抽象概念。
简单使用示例
@SneakyThrows
@Test
public void testJsonGenerator() {
JsonFactory factory = new JsonFactory();
// 此处最终输输出到OutputStreams输出流(此处输出到文件)
JsonGenerator jsonGenerator =
factory.createGenerator(FileUtil.newFile("person.json"), JsonEncoding.UTF8);
jsonGenerator.writeStartObject(); // 开始写,也就是这个符号 {
jsonGenerator.writeStringField("name", "YourBatman");
jsonGenerator.writeNumberField("age", 18);
// 写入Dog对象(枚举对象)
jsonGenerator.writeFieldName("dog");
jsonGenerator.writeStartObject(); // {
jsonGenerator.writeStringField("name", "旺财");
jsonGenerator.writeStringField("color", "WHITE");
jsonGenerator.writeEndObject(); // }
//写入一个数组格式
jsonGenerator.writeFieldName("hobbies"); // "hobbies" :
jsonGenerator.writeStartArray(); // [
jsonGenerator.writeString("篮球"); // "篮球"
jsonGenerator.writeString("football"); // "football"
jsonGenerator.writeEndArray(); // ]
jsonGenerator.writeEndObject(); //结束写,也就是这个符号 }
// 关闭IO流
jsonGenerator.close();
}
@SneakyThrows
@Test
public void testJsonParser() {
JsonFactory factory = new JsonFactory();
// 此处InputStream来自于文件
JsonParser jsonParser = factory.createParser(FileUtil.newFile("person.json"));
// 只要还没到末尾,也就是 } 这个符号,就一直读取
// {"name":"YourBatman","age":18,"dog":{"name":"旺财","color":"WHITE"},"hobbies":["篮球","football"]}
JsonToken jsonToken = jsonParser.nextToken(); // token类型
while (jsonToken != JsonToken.END_OBJECT) {
System.out.println("1. jsonToken === " + jsonToken);
String fieldname = jsonParser.getCurrentName();
if ("name".equals(fieldname)) {
jsonToken = jsonParser.nextToken();
System.out.println("==============token类型是:" + jsonToken);
System.out.println(jsonParser.getText());
} else if ("age".equals(fieldname)) {
jsonToken = jsonParser.nextToken();
System.out.println("==============token类型是:" + jsonToken);
System.out.println(jsonParser.getIntValue());
} else if ("dog".equals(fieldname)) {
jsonToken = jsonParser.nextToken();
System.out.println("==============token类型是:" + jsonToken);
while (jsonToken != JsonToken.END_OBJECT) {
System.out.println("2. jsonToken === " + jsonToken);
String dogFieldName = jsonParser.getCurrentName();
if ("name".equals(dogFieldName)) {
jsonToken = jsonParser.nextToken();
System.out.println("======================token类型是:" + jsonToken);
System.out.println(jsonParser.getText());
} else if ("color".equals(dogFieldName)) {
jsonToken = jsonParser.nextToken();
System.out.println("======================token类型是:" + jsonToken);
System.out.println(jsonParser.getText());
}
jsonToken = jsonParser.nextToken();
}
} else if ("hobbies".equals(fieldname)) {
jsonToken = jsonParser.nextToken();
System.out.println("==============token类型是:" + jsonToken);
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
System.out.println(jsonParser.getText());
}
}
jsonToken = jsonParser.nextToken();
}
// 关闭IO流
jsonParser.close();
}
person.json
{
"name": "YourBatman",
"age": 18,
"dog": {
"name": "旺财",
"color": "WHITE"
},
"hobbies": [
"篮球",
"football"
]
}
JsonToken
com.fasterxml.jackson.core.JsonToken
枚举类,定义了所有的 token 类型
JsonFactory
用于创建和配置 JsonParser
和 JsonGenerator
对 Feature 的支持包括支持判断是否启用、支持配置(同时支持判断)
-
JsonParser.Feature
、JsonGenerator.Feature
:支持配置 -
JsonParser.Feature
:支持判断,配置的方法已弃用,推荐使用JsonFactoryBuilder
进行配置 -
StreamReadFeature
、StreamWriteFeature
:支持判断不支持配置,使用JsonFactoryBuilder
进行配置 -
JsonWriteFeature
、JsonReadFeature
:不支持
是否启用 Feature 的实现
内部字段:
// 默认启用的 JsonFactory.Feature
protected final static int DEFAULT_FACTORY_FEATURE_FLAGS = JsonFactory.Feature.collectDefaults();
// 默认启用的 JsonParser.Feature
protected final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
// 默认启用的 JsonGenerator.Feature
protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
// 当前启用的 JsonFactory.Feature
protected int _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
// 当前启用的 JsonParser.Feature
protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
// 当前启用的 JsonGenerator.Feature
protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
这里的记录是否启用 Feature 的方法很巧妙,恰好之前在反射的代码那里看到过这种应用
参考 java.lang.reflect.Modifier
主要采用的方法是位运算,与 &
、 或 |
、非 ~
JsonFactory.Feature
的方法:
-
getMask
使用左移运算符<<
为每个枚举设置一个 mask ,用于标识 -
enabledIn
使用位运算&
判断该 Feature 是否被启用 -
collectDefaults
使用位运算|
计算默认启用的 Feature
JsonFactory
的方法:
-
isEnabled
类似于JsonFactory.Feature.enabledIn
-
enable
使用位运算|
-
disable
使用位运算&
、~
ObjectMapper objectMapper = new ObjectMapper();
JsonFactory jsonFactory = objectMapper.getFactory();
int parserFeatures = jsonFactory.getParserFeatures();
System.out.println(NumberUtil.getBinaryStr(parserFeatures)); // 100000000000001
int generatorFeatures = jsonFactory.getGeneratorFeatures();
System.out.println(NumberUtil.getBinaryStr(generatorFeatures)); // 11111
二进制数字的每个位置对应枚举的 ordinal
1 对应 Feature 枚举启用,0 对应不启用
SPI 方式创建
jackson-core
包提供了 ServiceLoader 机制创建 JsonFactory
实例的方法
ServiceLoader<JsonFactory> serviceLoader = ServiceLoader.load(JsonFactory.class);
Iterator<JsonFactory> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
直接创建
JsonFactory factory = new JsonFactory();
Builder 方式创建
JsonFactory jsonFactory = new JsonFactoryBuilder().build();
JsonGenerator
提供了 write{XXX}
系列方法
从 API 中可以看出,这种 Low-Level 的 API 是只能写基本类型的:如 int、long、BigInteger… 对于对象类型如 Date、Person 等,它都是不能直接写的
写对象需要配合 ObjectCodec
,而 ObjectMapper
是 ObjectCodec
的子类
-
使用
new JsonFactory()
创建的JsonGenerator
是不带ObjectCodec
的 -
使用
ObjectMapper.createGenerator
创建的JsonGenerator
是带ObjectCodec
的,也就是ObjectMapper
自身
JsonParser
提供了 get{XXX}Value
系列方法以及 getText
JsonFactory factory = new JsonFactory();
// 此处InputStream来自于文件
JsonParser jsonParser = factory.createParser(FileUtil.newFile("person.json"));
JsonToken jsonToken = jsonParser.nextToken();
while (jsonToken != null) {
System.out.println(jsonToken + " :: " + jsonParser.currentName() + " :: " + jsonParser.getText());
jsonToken = jsonParser.nextToken();
}
jsonParser.close();
输出结果
START_OBJECT :: null :: {
FIELD_NAME :: name :: name
VALUE_STRING :: name :: YourBatman
FIELD_NAME :: age :: age
VALUE_NUMBER_INT :: age :: 18
FIELD_NAME :: dog :: dog
START_OBJECT :: dog :: {
FIELD_NAME :: name :: name
VALUE_STRING :: name :: 旺财
FIELD_NAME :: color :: color
VALUE_STRING :: color :: WHITE
END_OBJECT :: dog :: }
FIELD_NAME :: hobbies :: hobbies
START_ARRAY :: hobbies :: [
VALUE_STRING :: null :: 篮球
VALUE_STRING :: null :: football
END_ARRAY :: hobbies :: ]
END_OBJECT :: null :: }
readValueAs{XXX}
系列方法需要配合 ObjectCodec
使用,同 JsonGenerator
ObjectMapper 相关
正常使用时,肯定还是用 ObjectMapper
这个门面类
ObjectMapper objectMapper = new ObjectMapper();
默认使用的 JsonFactory
实现是 MappingJsonFactory
,内部的 ObjectCodec
是 ObjectMapper
ObjectMapper
内部字段:
// 对应 JsonFactory
protected final JsonFactory _jsonFactory;
生成 JsonGenerator
和 JsonParser
,配置 Feature 都是直接调用 JsonFactory
方法,ObjectMapper
只是作为门面
示例
StringReader stringReader = new StringReader("{\"a\":'1'}");
ObjectMapper objectMapper = new ObjectMapper();
// 配置 JsonParser.Feature ,和直接使用 jsonFactory 配置等效
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 获取对象
JsonFactory jsonFactory = objectMapper.getFactory();
JsonGenerator jsonGenerator = objectMapper.createGenerator(System.out);
JsonParser jsonParser = objectMapper.createParser(stringReader);
// jsonGenerator 输出
jsonGenerator.writeObject(User.newDemoUser());
System.out.println();
// jsonParser 输出
JsonToken jsonToken = jsonParser.nextToken();
while (jsonToken != null) {
System.out.println(jsonToken + " :: " + jsonParser.currentName() + " :: " + jsonParser.getText());
jsonToken = jsonParser.nextToken();
}
相关方法
获取对象:
-
getFactory、tokenStreamFactory
-
createGenerator
-
createParser
Feature 相关:
-
isEnabled
-
configure
-
enable
-
disable
读写 JSON:
-
readValue
-
readTree
-
writeValue
-
writeValueAsString
-
writeValueAsBytes