org.json序列化Java 14 Record时字段全为null如何解决
原因说明
你的猜测完全正确。
20220320版本的org.json在序列化任意Java对象时,默认采用JavaBean规则扫描属性:仅识别方法名符合getXxx()、isXxx()格式的无参公开方法作为属性访问器,从方法名提取属性名、调用方法获取属性值。
Java Record不会自动生成带get前缀的getter方法,其内置的属性访问器和字段名完全一致,因此旧版本org.json扫描不到任何可读取的属性,最终生成的JSON所有字段值均为null。
兼容方案(不更换org.json依赖)
以下方案均保留org.json作为JSON处理依赖,无需切换到其他第三方库:
- 升级org.json到原生支持Record的版本
org.json官方从20230227版本开始正式适配Java Record,新增了专门的Record序列化逻辑,不需要修改任何业务代码,仅需替换pom中的依赖版本即可,推荐使用当前稳定版:
升级后原有<dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20240303</version> </dependency>new JSONObject(order).toString()的写法可以直接输出正确的JSON内容。 - 受项目约束无法升级版本时,在Record中手动添加符合JavaBean规范的getter方法
Java Record支持自定义普通实例方法,只需为每个字段补充对应带get前缀的无参方法,返回对应字段值,即可被旧版本org.json正常识别:public record Order( String id, String userId, String securityId, String type, Double price, Long quantity ) { // 适配org.json旧版本的JavaBean属性扫描规则 public String getId() { return id; } public String getUserId() { return userId; } public String getSecurityId() { return securityId; } public String getType() { return type; } public Double getPrice() { return price; } public Long getQuantity() { return quantity; } } - 手动逐字段构造JSONObject
如果既不能升级依赖,也不想修改Record的定义,可以在序列化时直接调用Record原生的同名访问器,手动将字段值放入JSONObject:
该方案适合字段数量少、序列化使用频次低的场景。Order order = new Order("", "Albert", "GOOGL", "SELL", 97.9, 90L); JSONObject jsonObj = new JSONObject(); jsonObj.put("id", order.id()); jsonObj.put("userId", order.userId()); jsonObj.put("securityId", order.securityId()); jsonObj.put("type", order.type()); jsonObj.put("price", order.price()); jsonObj.put("quantity", order.quantity()); String json = jsonObj.toString();
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

