Java解析REST API嵌套JSON后,如何修正输出为预期JSON格式
我需要处理REST API的嵌套JSON响应,httpsConn.getInputStream()返回的JSON内容如下:
{"data":[{"id":"1","name":"aaa","score":"90"},{"id":"2","name":"bbb","score":"85"}]}
现有Java代码:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); response = (MarkResponse)objectMapper.readValue(httpsConn.getInputStream(), MarkResponse.class);
POJO类定义:
public class MarkResponse { private int count; private List<MarkData> markData; // setter and getter. } public class MarkData { private String id; private String name; }
当前得到的响应为:
{"headers":{},"body":"MarkResponse [count=2 markData= [MarkData [id=1, name=aaa], MarkData [id=2,name=bbb]] ]","statusCode":"ACCEPTED","statusCodeValue":202}
而我预期的响应是:
{"headers":{},"body":"MarkResponse [count=2 markData= {\"id\":\"1\",\"name\":\"aaa\"},{\"id\":\"2\",\"name\":\"bbb\"} ]","statusCode":"ACCEPTED","statusCodeValue":202}
请问需要修改哪些代码才能得到预期的输出?
嘿,我来帮你搞定这个问题!你现在遇到的核心问题是:默认的POJOtoString()方法输出的是对象的结构化字符串,而不是你想要的JSON格式。咱们可以通过两种方式调整:
1. 手动序列化markData为JSON字符串(推荐)
这种方式更灵活,不会把序列化逻辑耦合到POJO里。在构造响应body的时候,用ObjectMapper把markData序列化成JSON格式的字符串,再拼接成你需要的格式:
// 假设你已经完成了反序列化得到response对象 ObjectMapper objectMapper = new ObjectMapper(); // 把markData序列化为JSON数组字符串 String markDataJson = objectMapper.writeValueAsString(response.getMarkData()); // 拼接成你想要的body格式 String body = String.format("MarkResponse [count=%d markData= %s ]", response.getCount(), markDataJson); // 然后把这个body赋值给你的响应对象即可
这样生成的markDataJson就是[{"id":"1","name":"aaa"},{"id":"2","name":"bbb"}],拼接后就和你预期的格式一致了。
2. 重写POJO的toString()方法(耦合性稍高)
如果你希望直接调用response.toString()就能得到目标格式,可以重写MarkResponse和MarkData的toString()方法:
修改MarkData的toString()
public class MarkData { private String id; private String name; // setter and getter @Override public String toString() { return String.format("{\"id\":\"%s\",\"name\":\"%s\"}", id, name); } }
修改MarkResponse的toString()
public class MarkResponse { private int count; private List<MarkData> markData; // setter and getter @Override public String toString() { // 把List<MarkData>转成逗号分隔的JSON格式字符串 String markDataStr = String.join(",", markData.stream().map(MarkData::toString).toList()); return String.format("MarkResponse [count=%d markData= %s ]", count, markDataStr); } }
这样当你调用response.toString()时,就能得到你预期的格式了。不过这种方式把格式逻辑写到了POJO里,如果后续格式有变化,需要修改POJO代码,灵活性不如第一种方式。
额外注意:count字段的赋值
另外,你的原始JSON响应里并没有count字段,当前得到的count=2应该是你后续代码手动设置的吧?如果是自动反序列化的话,count会是默认值0,记得要确保count的值是正确的(比如可以通过response.setCount(response.getMarkData().size())来设置)。
内容的提问来源于stack exchange,提问作者MSD

