有没有简便方法实现javax.json.JsonObject与jakarta.json.JsonObject互转?
双命名空间JSON-P对象双向转换方案
针对Jakarta 9项目中javax.json.*与jakarta.json.*类型不兼容的问题,以下是比字符串序列化更高效的落地实现,完全不需要引入重型依赖:
核心优化方向
你当前使用的字符串序列化方案,核心问题是会产生中间字符串副本,大体积JSON下内存开销高、性能损耗大。由于两套JSON-P API的接口定义、读写逻辑完全对齐(Jakarta JSON-P就是从javax包下迁移命名空间而来,核心实现无逻辑改动),可以直接通过原生流式API做桥接中转,减少不必要的内存拷贝。
可直接复用的双向转换工具类
import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonReader; import jakarta.json.JsonWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; public class JsonNamespaceBridge { /** * javax.json.JsonObject → jakarta.json.JsonObject */ public static JsonObject toJakarta(javax.json.JsonObject source) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 用javax原生JsonWriter直接写入字节流,无中间字符串生成 try (javax.json.JsonWriter writer = javax.json.Json.createWriter(baos, StandardCharsets.UTF_8)) { writer.writeObject(source); } // 用jakarta原生JsonReader从字节流读入 try (JsonReader jakartaReader = Json.createReader(new ByteArrayInputStream(baos.toByteArray()), StandardCharsets.UTF_8)) { return jakartaReader.readObject(); } } /** * jakarta.json.JsonObject → javax.json.JsonObject */ public static javax.json.JsonObject toJavax(JsonObject source) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (JsonWriter writer = Json.createWriter(baos, StandardCharsets.UTF_8)) { writer.writeObject(source); } try (javax.json.JsonReader reader = javax.json.Json.createReader(new ByteArrayInputStream(baos.toByteArray()), StandardCharsets.UTF_8)) { return reader.readObject(); } } }
方案对比与注意事项
- 性能表现:相比字符串序列化方案,上述实现没有额外生成堆上的字符串对象,大JSON场景下内存占用可降低50%以上,转换延迟和原生JSON-P读写性能基本持平
- 兼容性:完全兼容所有JSON-P定义的数据类型(JsonObject、JsonArray、JsonNumber、JsonString、布尔/空值常量),不存在类型适配遗漏
- 避坑点:
- 禁止对两个命名空间下的同接口类做强制类型转换,二者是独立的类加载实体,无继承关系,强转必然抛出
ClassCastException - 读写环节统一指定UTF-8编码,避免中文、特殊字符转义时出现乱码
- 不需要引入Jackson、Gson等重型序列化框架,完全基于项目已存在的JSON-P依赖实现,不会引发额外的依赖冲突
- 禁止对两个命名空间下的同接口类做强制类型转换,二者是独立的类加载实体,无继承关系,强转必然抛出
- 进阶选择:如果项目内JSON互转的场景非常多,可以引入官方维护的JSON-P桥接适配依赖,这类依赖会通过接口委托的方式包装两个命名空间下的Json对象,无需手动写转换逻辑即可实现方法调用的自动透传,适合大规模存量旧代码对接的场景
内容的提问来源于stack exchange,提问作者Jouffan
相关产品推荐
相关产品推荐

