如何反序列化一个 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
}
就这些。
困难在于,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
}
就这些。