使用Jackson ObjectMapper解析Strava API多态对象遇二维数组反序列化错误
嘿,我之前处理Strava API的多态流数据时也踩过类似的坑,来帮你排查下问题~
首先,咱们先从数据模型定义入手排查:
- 你确认
StravaStream2D里的data字段是float[][]类型吗?如果是,那本身没问题,但有时候Jackson对数组的嵌套解析不如List<List<Float>>灵活,你可以试着把类型换成List<List<Float>>试试,说不定能绕过一些数组反序列化的小问题。
接下来重点看自定义反序列化器的逻辑——这大概率是问题所在:
你提到已经能识别到用StravaStream2D类,但报错无法从VALUE_NUMBER_FLOAT反序列化为float[],这说明反序列化器在处理二维数组时,可能错误地把单个浮点数当成了float[]来解析。比如可能你在读取data字段时,还是用了处理一维数组的逻辑,或者JSON指针的位置不对。
举个正确的反序列化器写法参考:
@Override public StravaStream deserialize(JsonParser parser, DeserializationContext context) throws IOException { // 先把整个节点读成ObjectNode,避免指针位置混乱 ObjectNode rootNode = parser.readValueAsTree(); String streamType = rootNode.get("type").asText(); StravaStream resultStream; if ("latlng".equals(streamType)) { // 从ObjectNode里读取data字段,转成二维float数组 float[][] latLngData = parser.getCodec().treeToValue(rootNode.get("data"), float[][].class); resultStream = new StravaStream2D(); ((StravaStream2D) resultStream).setData(latLngData); } else { // 处理一维数据的情况 float[] singleDimData = parser.getCodec().treeToValue(rootNode.get("data"), float[].class); resultStream = new StravaStream1D(); ((StravaStream1D) resultStream).setData(singleDimData); } // 给公共字段赋值(比如type、original_size之类的) resultStream.setType(streamType); // ...其他字段的赋值逻辑 return resultStream; }
这里要注意:不能在读完ObjectNode后再直接用parser去读取data,否则会因为JSON指针已经移到末尾,读不到正确的数组结构,反而拿到单个数值,导致报错。一定要通过parser.getCodec().treeToValue()从已读取的ObjectNode里转换数据。
另外,还有个更省心的方案:用Jackson自带的多态注解代替自定义反序列化器,这样不用手动写解析逻辑,不容易出错:
// 基类上添加多态注解 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ // 把所有一维数据的type都列在这里 @JsonSubTypes.Type(value = StravaStream1D.class, names = {"distance", "time", "altitude", "velocity_smooth", "heartrate"}), // 二维数据只需要指定latlng @JsonSubTypes.Type(value = StravaStream2D.class, name = "latlng") }) public abstract class StravaStream { private String type; // 其他公共字段(比如 resolution, series_type等) // getter和setter } // 一维数据子类 public class StravaStream1D extends StravaStream { private float[] data; // getter和setter } // 二维数据子类 public class StravaStream2D extends StravaStream { private float[][] data; // getter和setter }
这样Jackson会自动根据type字段的值,自动选择对应的子类进行反序列化,完全不用自己写反序列化器,能避免很多手动处理的bug。
最后建议你先打印出要解析的latlng类型的JSON片段,确认data字段确实是嵌套数组格式(比如[[lat1,lng1],[lat2,lng2],...]),排除Strava API返回数据异常的可能。
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

