Apache Johnzon 配置参数详解
详解 Apache Johnzon 2.2.0 三层配置面——JSON-P 工厂配置、MapperBuilder 构建参数、JSON-B JsonbConfig 与注解、JVM 系统属性,均给出实测代码与真实回显,并附生产配置模板。
Apache Johnzon 配置参数详解
目标:Johnzon 是 Java 侧 JSON 库,无独立配置文件,全部参数分布在「JSON-P 工厂配置(Map)、MapperBuilder 链式参数、JSON-B JsonbConfig/注解、JVM 系统属性」四个层面。本文逐层逐项给出参数含义、修改方式、实测代码与真实回显,并附生产配置模板。已在 Ubuntu 22.04 + OpenJDK 17.0.2 + Johnzon 2.2.0 实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS,Kernel 6.8.0-138-generic,x86_64
- OpenJDK 17:17.0.2(build 17.0.2+8-86,
/opt/java/jdk-17.0.2) - Apache Maven:3.9.9(
/opt/maven) - Johnzon:2.2.0(johnzon-core / johnzon-mapper / johnzon-jsonb)
- Jakarta API:jakarta.json-api 2.1.3、jakarta.json.bind-api 3.0.1
- 示例工程目录:
/opt/johnzon-demo
二、前置条件
- 已完成 Johnzon 依赖引入(工程可编译,方法见《Ubuntu 22.04 安装 Apache Johnzon 指南》)。
- 本机安装 JDK(含
javap反汇编工具,用于查看参数 API 全集)。 - 演示类可独立执行:
java -cp target/classes:$(cat cp.txt) demo.XxxDemo(cp.txt 由mvn dependency:build-classpath -Dmdep.outputFile=cp.txt生成)。
三、参数查看与修改方式
Johnzon 无守护进程、无配置文件,参数在编码期写入。三层查看方式如下:
3.1 查看 MapperBuilder 参数全集(javap)
javap -classpath /root/.m2/repository/org/apache/johnzon/johnzon-mapper/2.2.0/johnzon-mapper-2.2.0.jar \
org.apache.johnzon.mapper.MapperBuilder | grep "set" | head -12
真实回显(节选,全集约 50 个 setter):
public org.apache.johnzon.mapper.MapperBuilder setSnippetMaxLength(int);
public org.apache.johnzon.mapper.MapperBuilder setUseShortISO8601Format(boolean);
public org.apache.johnzon.mapper.MapperBuilder setAdaptersDateTimeFormatter(java.time.format.DateTimeFormatter);
public org.apache.johnzon.mapper.MapperBuilder setInterfaceImplementationMapping(java.util.Map<java.lang.Class<?>, java.lang.Class<?>>);
public org.apache.johnzon.mapper.MapperBuilder setFailOnUnknownProperties(boolean);
public org.apache.johnzon.mapper.MapperBuilder setIgnoreFieldsForType(java.lang.Class<?>, java.lang.String...);
public org.apache.johnzon.mapper.MapperBuilder setSupportGetterForCollections(boolean);
public org.apache.johnzon.mapper.MapperBuilder setSupportsComments(boolean);
public org.apache.johnzon.mapper.MapperBuilder setPretty(boolean);
public org.apache.johnzon.mapper.MapperBuilder setBufferSize(int);
public org.apache.johnzon.mapper.MapperBuilder setBufferStrategy(java.lang.String);
public org.apache.johnzon.mapper.MapperBuilder setMaxSize(int);
3.2 查看 JsonbConfig 标准属性键(javap)
javap -classpath /root/.m2/repository/jakarta/json/bind/jakarta.json.bind-api/3.0.1/jakarta.json.bind-api-3.0.1.jar \
jakarta.json.bind.JsonbConfig | grep "public static final"
真实回显:
public static final java.lang.String FORMATTING;
public static final java.lang.String ENCODING;
public static final java.lang.String PROPERTY_NAMING_STRATEGY;
public static final java.lang.String PROPERTY_ORDER_STRATEGY;
public static final java.lang.String NULL_VALUES;
public static final java.lang.String STRICT_IJSON;
public static final java.lang.String PROPERTY_VISIBILITY_STRATEGY;
public static final java.lang.String ADAPTERS;
public static final java.lang.String SERIALIZERS;
public static final java.lang.String DESERIALIZERS;
public static final java.lang.String BINARY_DATA_STRATEGY;
public static final java.lang.String DATE_FORMAT;
public static final java.lang.String LOCALE;
public static final java.lang.String CREATOR_PARAMETERS_REQUIRED;
3.3 查看运行期系统属性(-XshowSettings)
java -Djohnzon.max-big-decimal-scale=500 -XshowSettings:properties -version 2>&1 | grep johnzon
真实回显:
johnzon.max-big-decimal-scale = 500
3.4 修改方式汇总
| 层面 | 修改入口 | 生效方式 |
|---|---|---|
| JSON-P 工厂 | Json.create*Factory(Map) / JsonbConfig | 传入配置 Map,创建工厂时生效 |
| Mapper | new MapperBuilder().setXxx(...).build() | 链式设置,build 时生效 |
| JSON-B | new JsonbConfig().withXxx(...) / 注解 | 传入 JsonbBuilder.create(cfg) 生效 |
| JVM 系统属性 | java -Djohnzon.xxx=value | JVM 启动参数,Provider 初始化时读取 |
四、参数总览
4.1 JSON-P 工厂配置(johnzon-core)
| 配置键 | 类型 | 默认 | 说明 |
|---|---|---|---|
| jakarta.json.stream.JsonGenerator.pretty-printing | Boolean | false | 美化输出(缩进 + 换行) |
| jakarta.json.JsonConfig.keyStrategy | String | DEFAULT | 重复键策略:DEFAULT(后值覆盖)/ TRUE(拒绝)/ FIRST(保留首值) |
| johnzon.rejectDuplicateKeys | String | DEFAULT | 同上(Johnzon 私有键,二选一) |
4.2 MapperBuilder 常用构建参数(johnzon-mapper)
| 参数 | 默认 | 说明 |
|---|---|---|
| setPretty(boolean) | false | 美化输出 |
| setSkipNull(boolean) | false | 序列化时跳过 null 值属性 |
| setAttributeOrder(Comparator<String>) | 无 | 属性输出顺序 |
| setFailOnUnknownProperties(boolean) | false | 反序列化遇到未知属性是否报错 |
| setMaxSize(int) | 无限制 | 单字符串/数字最大长度(读侧限制) |
| setBufferStrategy(String) | QUEUE | 缓冲策略:SINGLETON / THREAD_LOCAL / QUEUE / BY_INSTANCE |
| setBufferSize(int) | 16384 | 缓冲区初始大小 |
| setEncoding(String) | UTF-8 | 流式读写编码 |
| setTreatByteArrayAsBase64(boolean) | false | byte[] 序列化为 Base64 字符串(默认输出数字数组) |
| setTreatByteArrayAsBase64URL(boolean) | false | byte[] 序列化为 Base64URL 字符串 |
| setUseBigDecimalForFloats(boolean) | false | 浮点用 BigDecimal 处理 |
| setMaxBigDecimalScale(int) | 1000 | BigDecimal scale 上限(可被系统属性覆盖) |
| setSkipEmptyArray(boolean) | false | 跳过空数组属性 |
| setSupportHiddenAccess(boolean) | false | 支持访问隐藏字段 |
| setVersion(int) | 1 | Mapper 内部映射版本 |
| setDoCloseOnStreams(boolean) | false | 读写后是否关闭传入流 |
4.3 JSON-B JsonbConfig 参数(jakarta.json.bind-api,Johnzon 实现)
| 属性键(JsonbConfig 常量) | 说明 |
|---|---|
| FORMATTING | 是否美化输出(Boolean) |
| ENCODING | 编码(String,如 UTF-8) |
| PROPERTY_NAMING_STRATEGY | 命名策略(如 LOWER_CASE_WITH_UNDERSCORES) |
| PROPERTY_ORDER_STRATEGY | 属性排序策略 |
| NULL_VALUES | 是否序列化 null |
| PROPERTY_VISIBILITY_STRATEGY | 字段/方法可见性策略 |
| ADAPTERS / SERIALIZERS / DESERIALIZERS | 自定义适配器/序列化器/反序列化器 |
| DATE_FORMAT | 日期格式(String) |
| LOCALE | 区域设置 |
| BINARY_DATA_STRATEGY | byte[] 序列化策略(BASE_64 / BASE_64_URL) |
| STRICT_IJSON | 是否严格 I-JSON |
| CREATOR_PARAMETERS_REQUIRED | 构造参数是否必需 |
4.4 JVM 系统属性(johnzon-core 内部读取)
| 属性键 | 默认 | 说明 |
|---|---|---|
| johnzon.max-big-decimal-scale | 1000 | BigDecimal scale 上限(Provider 级全局) |
| org.apache.johnzon.buffer-strategy | QUEUE | JSON-P 工厂默认缓冲策略(SINGLETON / THREAD_LOCAL / QUEUE / BY_INSTANCE) |
五、核心参数分类详解
5.1 JSON-P 美化输出(pretty-printing)
JsonWriterFactory wf = Json.createWriterFactory(Map.of(JsonGenerator.PRETTY_PRINTING, true));
StringWriter sw = new StringWriter();
try (JsonWriter w = wf.createWriter(sw)) { w.writeObject(obj); }
真实回显(对比紧凑输出):
[build] compact = {"id":1001,"name":"johnzon","price":49.9,"tags":["json","parser"],"author":{"name":"Apache","site":"johnzon.apache.org"}}
[pretty]
{
"id":1001,
"name":"johnzon",
"price":49.9,
"tags":[
"json",
"parser"
],
"author":{
"name":"Apache",
"site":"johnzon.apache.org"
}
}
5.2 JSON-P 重复键策略(keyStrategy / johnzon.rejectDuplicateKeys)
通过 Json.createBuilderFactory(Map) 传入策略,取值 DEFAULT / TRUE / FIRST:
JsonBuilderFactory strict = Json.createBuilderFactory(
Map.of("jakarta.json.JsonConfig.keyStrategy", "TRUE"));
try {
System.out.println("[keyStrategy=TRUE] " + strict.createObjectBuilder().add("k", 1).add("k", 2).build());
} catch (Exception e) {
System.out.println("[keyStrategy=TRUE] " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
JsonBuilderFactory first = Json.createBuilderFactory(
Map.of("jakarta.json.JsonConfig.keyStrategy", "FIRST"));
System.out.println("[keyStrategy=FIRST] " + first.createObjectBuilder().add("k", 1).add("k", 2).build());
真实回显:
[keyStrategy=TRUE] JsonException: Rejected key: 'k', already present
[keyStrategy=FIRST] {"k":1}
Johnzon 私有键同样生效(实测):
JsonBuilderFactory strict2 = Json.createBuilderFactory(
Map.of("johnzon.rejectDuplicateKeys", "TRUE"));
真实回显:
[johnzon.rejectDuplicateKeys=TRUE] JsonException: Rejected key: 'k', already present
⚠️ 注意:不配置时默认
DEFAULT(后值覆盖前值),重复输入{"k":1,"k":2}读出k=2;对上游数据可信度要求高的场景建议显式设TRUE。
5.3 Mapper 输出控制(setPretty / setSkipNull / setAttributeOrder)
List<String> order = Arrays.asList("id", "host", "port", "user", "password");
Mapper pretty = new MapperBuilder()
.setPretty(true)
.setSkipNull(true)
.setAttributeOrder(Comparator.comparingInt(order::indexOf))
.build();
System.out.println(pretty.writeObjectAsString(server));
真实回显:
{
"internal":"hidden",
"id":1,
"host":"web1.example.com",
"port":22,
"user":"root",
"password":"q1w2e3r4"
}
💡 说明:默认(无 setAttributeOrder)输出按字段访问模式返回顺序(
{"password":"q1w2e3r4","internal":"hidden","port":22,"host":"web1.example.com","id":1,"user":"root"});排序比较器对未列入 order 的属性返回 -1,因此internal排在首位——需要固定顺序时应把全部属性列入比较器。
5.4 Mapper 解析控制(setFailOnUnknownProperties / setMaxSize)
默认容忍未知属性,开启严格模式后报错(实测):
Mapper strict = new MapperBuilder().setFailOnUnknownProperties(true).build();
strict.readObject("{\"x\":10,\"zzz\":5}", Point.class);
真实回显:
[strict] MapperException: (fail on unknown properties): [zzz]
setMaxSize 限制读入单个字符串/数字的最大长度(实测设 16):
Mapper small = new MapperBuilder().setMaxSize(16).build();
small.readObject("{\"pad\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}", Map.class);
真实回显:
[read maxSize=16] JsonParsingException: Too many characters. Maximum string/number length of 16 exceeded on [lineNumber=1, columnNumber=42, streamOffset=41]. Maybe increase org.apache.johnzon.max-string-length in jsonp factory properties or system properties.
💡 说明:该参数是防大 JSON 打爆内存的读侧护栏,报错信息同时给出定位(行/列/偏移)与调大方式。
5.5 Mapper 缓冲策略与容量(setBufferStrategy / setBufferSize)
setBufferStrategy 合法值四个:SINGLETON、THREAD_LOCAL、QUEUE、BY_INSTANCE,逐个设置均构建成功(实测输出):
[buffer=SINGLETON] ok
[buffer=THREAD_LOCAL] ok
[buffer=QUEUE] ok
[buffer=BY_INSTANCE] ok
非法值直接给出合法清单(实测):
[buffer=FOO] IllegalArgumentException: Could not load Johnzon BufferStrategy FOO. Valid BufferStrategies are [SINGLETON, QUEUE, BY_INSTANCE, THREAD_LOCAL] or a fully qualified class name of an implementation of org.apache.johnzon.core.BufferStrategy
选型说明:默认策略由系统属性 org.apache.johnzon.buffer-strategy 控制(未设置时为 QUEUE);THREAD_LOCAL 按线程复用,适合高并发读多写少;QUEUE 跨线程回收复用;SINGLETON 全局单块复用(仅单线程场景);BY_INSTANCE 每次新建(排障对照用)。
5.6 byte[] 序列化格式(setTreatByteArrayAsBase64)
默认 byte[] 输出为数字数组,开启后输出 Base64(实测对比):
Mapper b64 = new MapperBuilder().setTreatByteArrayAsBase64(true).build();
Mapper raw = new MapperBuilder().build();
真实回显:
[base64] {"data":"am9obnpvbg=="}
[raw] {"data":[106,111,104,110,122,111,110]}
5.7 JSON-B JsonbConfig 参数(withFormatting 实测)
JsonbConfig cfg = new JsonbConfig().withFormatting(true);
Jsonb pretty = JsonbBuilder.create(cfg);
System.out.println(pretty.toJson(user));
真实回显:
{
"id":1,
"role":"admin",
"createdAt":"2026-10-11 10:30:00",
"comment":null,
"username":"root"
}
💡 说明:
createdAt的yyyy-MM-dd HH:mm:ss格式来自 POJO 上的@JsonbDateFormat;comment为 null 仍输出来自@JsonbNillable;name字段输出为username来自@JsonbProperty(注解见 5.8)。
5.8 注解驱动的映射配置(Johnzon 注解)
| 注解 | 作用 | 实测效果 |
|---|---|---|
| @JohnzonProperty("login_name") | 重命名序列化键 | name 输出为 login_name |
| @JohnzonIgnore | 忽略该属性 | password 不出现在输出中 |
| @JohnzonConverter(XxxConverter.class) | 自定义类型转换器 | token 输出为掩码 ****** |
| @JohnzonIgnoreNested | 忽略嵌套对象属性 | — |
| @JohnzonRecord.Name | record 组件命名 | — |
| @JohnzonDeduplicateObjects | 对象去重 | — |
示例(Account 类含三个注解):
Mapper mapper = new MapperBuilder().build();
String json = mapper.writeObjectAsString(new Account());
真实回显:
[write] {"login_name":"root","token":"******"}
反序列化同样生效(password 字段被忽略后保留字段默认值 q1w2e3r4):
[read] name=admin password=q1w2e3r4 token=decoded
5.9 JVM 系统属性(johnzon.max-big-decimal-scale)
johnzon-core 的 JsonProviderImpl 启动时读取 johnzon.max-big-decimal-scale,默认 1000(可通过 javap -c 观察到 Integer.getInteger("johnzon.max-big-decimal-scale", 1000))。设置与验证方式:
java -Djohnzon.max-big-decimal-scale=500 -XshowSettings:properties -version 2>&1 | grep johnzon
真实回显:
johnzon.max-big-decimal-scale = 500
Mapper 侧对应 MapperBuilder.setMaxBigDecimalScale(int),可按工程粒度覆盖全局默认。
5.10 Maven 依赖与 provided 范围
Johnzon 2.2.0 各模块 POM 将 jakarta API 声明为 provided(实测解析 johnzon-jsonb POM:jakarta.json.bind-api scope=provided),因此工程必须显式依赖 jakarta.json:jakarta.json-api:2.1.3 与 jakarta.json.bind:jakarta.json.bind-api:3.0.1。缺失时编译报:
[ERROR] class file for jakarta.json.JsonValue not found
六、生产配置模板
适用场景:中大型 Java 服务端应用(16GB 内存、多核,JSON 吞吐中等,日解析百万级消息);以下为推荐的三层组合配置(代码模板,Johnzon 为库,随应用进程启动生效)。
// 1) Mapper 层:读侧护栏 + 输出控制(推荐在单例中构建并复用)
Mapper mapper = new MapperBuilder()
.setEncoding("UTF-8")
.setFailOnUnknownProperties(true) // 严格模式:上游字段变更早发现
.setMaxSize(16 * 1024 * 1024) // 单字符串/数字上限 16MB,防大报文打爆内存
.setBufferStrategy("QUEUE") // 缓冲跨线程复用
.setSkipNull(true) // 输出剔除 null,减小报文
.setTreatByteArrayAsBase64(true) // 二进制走 Base64,便于跨语言
.build();
// 2) JSON-B 层:标准绑定 + 格式化关闭(生产输出保持紧凑)
JsonbConfig cfg = new JsonbConfig()
.withFormatting(false)
.withEncoding("UTF-8")
.withNullValues(false);
Jsonb jsonb = JsonbBuilder.create(cfg);
// 3) JSON-P 层:解析工厂开启重复键拒绝(可选,防脏数据)
JsonBuilderFactory factory = Json.createBuilderFactory(
Map.of("jakarta.json.JsonConfig.keyStrategy", "TRUE"));
配套 JVM 与构建参数(应用进程堆按 256–512MB 起步,按流量扩容):
# 应用进程启动示例(演示工程)
java -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -Djohnzon.max-big-decimal-scale=1000 -jar app.jar
# Maven 构建阶段
MAVEN_OPTS="-Xms256m -Xmx512m" mvn package -DskipTests
生效复核(堆上限 512MB = 536870912 字节):
java -Xms256m -Xmx512m -XX:+PrintFlagsFinal -version 2>/dev/null | grep MaxHeapSize
真实回显:
size_t MaxHeapSize = 536870912 {product} {command line}
七、常见问题
Q1:setBufferStrategy("xxx") 报 IllegalArgumentException
合法值仅 SINGLETON、QUEUE、BY_INSTANCE、THREAD_LOCAL(错误信息会列出全部合法值),或传一个实现 org.apache.johnzon.core.BufferStrategy 的类的全限定名。
Q2:设了 @JsonbPropertyOrder/setAttributeOrder 但顺序不符合预期
setAttributeOrder 基于 Comparator,未列入顺序表的属性 indexOf 为 -1 会排最前;把全部属性列入比较器即可(见 5.3 说明)。
Q3:-Djohnzon.rejectDuplicateKeys=true 对 Json.createObjectBuilder() 无效
重复键策略挂在工厂配置 Map 上(Json.createBuilderFactory(Map.of("jakarta.json.JsonConfig.keyStrategy","TRUE"))),通过默认静态方法创建的 Builder 走 DEFAULT 模式;实测系统属性方式对 Builder 直建不生效,请按工厂配置使用。
Q4:读 JSON 报 JsonParsingException: Too many characters
命中 setMaxSize 护栏。确认业务报文上限后调大该值(如 16MB),错误信息中会提示 Maybe increase org.apache.johnzon.max-string-length。
Q5:JSON-B 输出属性名与字段名不一致
检查 POJO 上的 @JsonbProperty(重命名)、PROPERTY_NAMING_STRATEGY(全局命名策略)与 @JohnzonProperty(Johnzon 注解)三者叠加效果。
Q6:JsonbConfig.withFormatting 不生效
确认配置传入了创建入口:JsonbBuilder.create(cfg);JsonbBuilder.create() 无参创建的是默认配置实例,二者不共享。
八、参考链接
- Apache Johnzon 官网(文档):https://johnzon.apache.org/
- MapperBuilder API(源码):https://github.com/apache/johnzon/blob/main/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
- Jakarta JSON Processing 2.1:https://jakarta.ee/specifications/jsonp/2.1/
- Jakarta JSON Binding 3.0:https://jakarta.ee/specifications/jsonb/3.0/
- Johnzon Maven 仓库:https://repo.maven.apache.org/maven2/org/apache/johnzon/