第三方API转自定义Java对象后,Controller返回JSON无字段名问题
问题:Controller返回的JSON无字段名,仅为嵌套数组
我把第三方API的响应解析成自定义Java类,解析过程没问题,但自己的Controller返回的JSON里没有对象的字段名,只有数组嵌套数组的结构,和原第三方API的响应格式一样。代码里的Getter、Setter都正常工作。
服务层解析方法
public List<Kline> klines(String symbol, String interval) { try { LinkedHashMap<String, Object> parameters = new LinkedHashMap<>(); parameters.put("symbol", symbol); parameters.put("interval", interval); String result = client.createMarket().klines(parameters); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(result, new TypeReference<List<Kline>>() { }); } catch (Exception e) { e.printStackTrace(); return null; } }
Controller接口
@GetMapping("/klines") public List<Kline> klines() { return service.klines("BTCUSDT", "1h"); }
返回的JSON格式(无字段名)
返回内容为嵌套数组结构,示例:[[1690000000, 30000, 31000, ...], [...]],每个子数组对应一个Kline对象,但没有字段名标识。
我的Kline POJO类
@Data @JsonFormat(shape = JsonFormat.Shape.ARRAY) @JsonPropertyOrder({ "openTime", "open", "high", "low", "close", "volume", "closeTime", "quoteAssetVolume", "numberOfTrades", "takerBuyBaseAssetVolume", "takerBuyQuoteAssetVolume" }) @JsonIgnoreProperties(ignoreUnknown = true) public class Kline { private Long openTime; private double open; private double high; private double low; private double close; private double volume; private Long closeTime; private double quoteAssetVolume; private int numberOfTrades; private double takerBuyBaseAssetVolume; private double takerBuyQuoteAssetVolume; }
解决方法
问题出在@JsonFormat(shape = JsonFormat.Shape.ARRAY)注解上——它是双向生效的:既会让Jackson把第三方的数组格式反序列化成Kline对象,也会让Jackson把Kline对象序列化成数组格式返回给前端。
要实现“反序列化用数组转对象,序列化用对象转带字段名的JSON”,有两种简单方案:
方案1:拆分DTO和业务类
- 新建一个
KlineDto类,保留@JsonFormat(shape = JsonFormat.Shape.ARRAY)和@JsonPropertyOrder注解,专门用来接收第三方API的数组响应; - 业务用的
Kline类去掉这两个注解,只保留@Data和@JsonIgnoreProperties; - 在服务层把
List<KlineDto>转换成List<Kline>再返回:
// 示例转换逻辑 List<KlineDto> dtoList = objectMapper.readValue(result, new TypeReference<List<KlineDto>>() { }); return dtoList.stream().map(dto -> { Kline kline = new Kline(); BeanUtils.copyProperties(dto, kline); return kline; }).collect(Collectors.toList());
方案2:自定义反序列化器(无需额外类)
去掉Kline类上的@JsonFormat(shape = JsonFormat.Shape.ARRAY),然后给Kline类添加@JsonDeserialize(using = KlineDeserializer.class),自定义一个反序列化器处理数组格式:
public class KlineDeserializer extends JsonDeserializer<Kline> { @Override public Kline deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); Kline kline = new Kline(); kline.setOpenTime(node.get(0).asLong()); kline.setOpen(node.get(1).asDouble()); kline.setHigh(node.get(2).asDouble()); kline.setLow(node.get(3).asDouble()); kline.setClose(node.get(4).asDouble()); kline.setVolume(node.get(5).asDouble()); kline.setCloseTime(node.get(6).asLong()); kline.setQuoteAssetVolume(node.get(7).asDouble()); kline.setNumberOfTrades(node.get(8).asInt()); kline.setTakerBuyBaseAssetVolume(node.get(9).asDouble()); kline.setTakerBuyQuoteAssetVolume(node.get(10).asDouble()); return kline; } }
这样反序列化时用自定义逻辑把数组转成对象,序列化时Jackson会默认输出带字段名的JSON结构。
内容的提问来源于stack exchange,提问作者BitQueen
相关产品推荐
相关产品推荐

