Apache Johnzon 配置参数详解

详解 Apache Johnzon 2.2.0 三层配置面——JSON-P 工厂配置、MapperBuilder 构建参数、JSON-B JsonbConfig 与注解、JVM 系统属性,均给出实测代码与真实回显,并附生产配置模板。

Apache JohnzonApache Johnzon参数调优JavaApache配置详解2026/10/12

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,创建工厂时生效
Mappernew MapperBuilder().setXxx(...).build()链式设置,build 时生效
JSON-Bnew JsonbConfig().withXxx(...) / 注解传入 JsonbBuilder.create(cfg) 生效
JVM 系统属性java -Djohnzon.xxx=valueJVM 启动参数,Provider 初始化时读取

四、参数总览

4.1 JSON-P 工厂配置(johnzon-core)

配置键类型默认说明
jakarta.json.stream.JsonGenerator.pretty-printingBooleanfalse美化输出(缩进 + 换行)
jakarta.json.JsonConfig.keyStrategyStringDEFAULT重复键策略:DEFAULT(后值覆盖)/ TRUE(拒绝)/ FIRST(保留首值)
johnzon.rejectDuplicateKeysStringDEFAULT同上(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)falsebyte[] 序列化为 Base64 字符串(默认输出数字数组)
setTreatByteArrayAsBase64URL(boolean)falsebyte[] 序列化为 Base64URL 字符串
setUseBigDecimalForFloats(boolean)false浮点用 BigDecimal 处理
setMaxBigDecimalScale(int)1000BigDecimal scale 上限(可被系统属性覆盖)
setSkipEmptyArray(boolean)false跳过空数组属性
setSupportHiddenAccess(boolean)false支持访问隐藏字段
setVersion(int)1Mapper 内部映射版本
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_STRATEGYbyte[] 序列化策略(BASE_64 / BASE_64_URL)
STRICT_IJSON是否严格 I-JSON
CREATOR_PARAMETERS_REQUIRED构造参数是否必需

4.4 JVM 系统属性(johnzon-core 内部读取)

属性键默认说明
johnzon.max-big-decimal-scale1000BigDecimal scale 上限(Provider 级全局)
org.apache.johnzon.buffer-strategyQUEUEJSON-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.Namerecord 组件命名—
@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() 无参创建的是默认配置实例,二者不共享。

八、参考链接