Jackson中ACCEPT_SINGLE_VALUE_AS_ARRAY与Shape.ARRAY兼容问题排查
你遇到的报错根源是:BitfinexOhlcWsResp被标记为@JsonFormat(shape = JsonFormat.Shape.ARRAY),Jackson会按字段顺序解析JSON数组的元素。第二个字段是List<BitfinexCandle>,Jackson期望这个位置是包含多个BitfinexCandle数组的JSON数组(即[[1716181800000,...], [...]]),但你的输入中这个位置是单个BitfinexCandle的JSON数组([1716181800000,...])。
此时Jackson错误地将这个单个BitfinexCandle数组里的每一个元素(比如第一个数字1716181800000)尝试解析成BitfinexCandle对象,但BitfinexCandle本身要求输入是数组,因此抛出“无法从非数组表示反序列化POJO”的错误。
有两种简洁的方式解决这个问题:
方案1:利用@JsonCreator手动处理单/多蜡烛场景
给BitfinexOhlcWsResp添加两个构造函数,分别处理单个蜡烛和多个蜡烛的输入,让Jackson自动匹配:
@Data @JsonFormat(shape = JsonFormat.Shape.ARRAY) public class BitfinexOhlcWsResp { Integer channelId; List<BitfinexCandle> candles; // 处理单个蜡烛的情况:将单个BitfinexCandle包装成List @JsonCreator public BitfinexOhlcWsResp(Integer channelId, BitfinexCandle candle) { this.channelId = channelId; this.candles = Collections.singletonList(candle); } // 处理多个蜡烛的情况:直接接收List @JsonCreator public BitfinexOhlcWsResp(Integer channelId, List<BitfinexCandle> candles) { this.channelId = channelId; this.candles = candles; } }
这种方式无需额外配置ObjectMapper,同时兼容单蜡烛和多蜡烛的输入格式。
方案2:结合@JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY和全局配置
保留原模型结构,调整candles字段的注解,确保Jackson将单个BitfinexCandle数组识别为List的单元素:
@Data @JsonFormat(shape = JsonFormat.Shape.ARRAY) public class BitfinexOhlcWsResp { Integer channelId; // 开启字段级别的单值转数组特性 @JsonFormat(with = {JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY}) List<BitfinexCandle> candles; }
同时确保ObjectMapper的全局配置中开启ACCEPT_SINGLE_VALUE_AS_ARRAY(你已经配置了,无需修改):
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
这个配置会告诉Jackson:当candles字段期望接收数组(List)时,若输入是单个值(这里是单个BitfinexCandle的数组),自动将其包装为单元素数组。
使用你的测试输入[158587,[1716181800000,67222,67224,67224,67222,0.0022]],两种方案都能正常反序列化出BitfinexOhlcWsResp对象,且candles列表包含一个BitfinexCandle元素。
内容的提问来源于stack exchange,提问作者greengold

