如何反序列化一个 json 数组后跟一个正常的 属性 到 jackson 中的 pojo。阵列单独工作

How to deserialize a json array followed by a normal property into a pojo in jackson. The array alone works

困难在于,json 标签在 Kraken api 的其余响应中是部分动态的。首先我介绍一个工作案例。我连接 Kraken 交易 api 以获取货币作为资产,并在 json.

中得到以下结果
{
    "error": [],
    "result": {
        "AAVE": {
            "aclass": "currency",
            "altname": "AAVE",
            "decimals": 10,
            "display_decimals": 5
        },
        "ZUSD": {
            "aclass": "currency",
            "altname": "USD",
            "decimals": 4,
            "display_decimals": 2
        }
    }
}

本例中的 AAVA 和 ZUSD 是动态标签。我使用嵌入式 Jackson 在 OpenFeign 框架中解析它。结果部分包含以下通用 class:

public class Response<T> {
    
    private List<String> error = new ArrayList<>();
    private T result;
    
    // getter and setters
}

作为资产的根 class,动态标签 AAVA 和 ZUSD 由 Map 处理:

public class AssetInfoResponse extends 
              Response<Map<String, AssetInfo>> {
}

pojo 资产信息:

public class AssetInfo implements Serializable{

    @JsonProperty("altname")
    private String alternateName;

    @JsonProperty("aclass")
    private String assetClass;

    @JsonProperty("decimals")
    private Byte decimals;

    @JsonProperty("display_decimals")
    private Byte displayDecimals;

    // getters, setters ...
}

上面的案例很完美,还有动态标签的解决方案。

这是 ohlc 数据的响应,看起来很相似,我不知道如何解决下一个案例中的反序列化问题:

{
    "error": [],
    "result": {
        "XXBTZEUR": [
            [
                1613212500,
                "39000.1",
                "39010.1",
                "38972.3",
                "38994.1",
                "38998.1",
                "3.23811638",
                70
            ],
            [
                1613212560,
                "38994.3",
                "39014.5",
                "38994.3",
                "39014.5",
                "38997.3",
                "0.95105956",
                11
            ]
        ],
        "last": 1613212500
    }
}

问题的原因是"last": 1613212500 属性行。当我删除此行时,可以毫无问题地解析响应。我尝试用下面的classes来解决,Response是上面描述的class.

public class OhlcLastResponse<T> extends Response<T> {

    private Long last;
   
    // getters and setters

}

下一个 class 扩展了前一个 class 并且是对象映射器的根 class:

public class OhlcResponse
      extends OhlcLastResponse<Map<String, List<Candelstick>>> {
}

以及保存烛条数据的 pojo:

@JsonFormat(shape = JsonFormat.Shape.ARRAY)
@JsonPropertyOrder({ "time", "open", "high", "low",
                     "close", "vwap", "volume", "count" })
public class Candelstick implements Serializable {
    
    private Integer time;

    private BigDecimal open;

    private BigDecimal high;

    private BigDecimal low;

    private BigDecimal close;

    private BigDecimal vwap;

    private BigDecimal volume;

    private Integer count;

    // getters and setters ...
}

这里是错误:

                "38997.3",
                "0.95105956",
                11
            ]
        ],
        "last": 1613212500
    }
}
"; line: 26, column: 11] (through reference chain: OhlcResponse["result"]->java.util.LinkedHashMap["last"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)

Jackson 试图将 last 属性 放入地图,但地图已被 ], 完成。第 26 行是带有 last 标签在 json 文件中。

是否可以解析这个json?我想一定是可以的,因为数组是用方括号括起来的。

我在 github 上托管了其余客户端。要重现错误,只需克隆它并 运行 mvn test.

解决方案是反序列化器,因为在这种情况下类型处理非常困难。反序列化器在数组或单个最后一个值这两种情况之间做出决定,并在数组的情况下调用 CandleStick Class:

的反序列化器
public class OhlcDeserializer extends JsonDeserializer<OhclPayload> {

    @Override
    public OhclPayload deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {

        List<CandleStick> candleSticks = new ArrayList<CandleStick>();

        Long last = null;

        ObjectCodec objectCodec = p.getCodec();
        JsonNode jsonNode = objectCodec.readTree(p);

        Iterator<Entry<String, JsonNode>> payloadIterator = jsonNode.fields();
        while (payloadIterator.hasNext()) {
            Map.Entry<String, JsonNode> entry = payloadIterator.next();
            if (entry.getKey().equals("last")) {
                last = entry.getValue().asLong();
            } else if (entry.getValue().isArray()) {
                for (JsonNode node : entry.getValue()) {
                    CandleStick cs = p.getCodec().treeToValue(node, CandleStick.class);
                    candleSticks.add(cs);
                }
            }
        }

        return new OhclPayload(candleSticks, last);
    }

}

我将 OhclResponse 更改为:

public class OhlcResponse extends Response<OhclPayload> {
}

并为解串器插入一个 OhlcPayload class:

@JsonDeserialize(using = OhlcDeserializer.class)
public class OhclPayload {

    private List<CandleStick> candleSticks;

    private Long last;
    // getters and setters
}

就这些。