用杰克逊解析数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用杰克逊解析数组相关的知识,希望对你有一定的参考价值。
我想用杰克逊解析下面的Json,但我不确定如何构建实体。
[
CHAN_ID,
[
[
SYMBOL,
STATUS,
AMOUNT,
BASE_PRICE,
MARGIN_FUNDING,
MARGIN_FUNDING_TYPE,
PL,
PL_PERC,
PRICE_LIQ,
LEVERAGE,
...
],
...
]
]
这是我到目前为止:
@Getter
@Setter
@EqualsAndHashCode
@ToString
@NoArgsConstructor
public class Position {
@JsonProperty("SYMBOL")
private String symbol;
@JsonProperty("STATUS")
private String status;
@JsonProperty("AMOUNT")
private Decimal amount;
@JsonProperty("BASE_PRICE")
private Decimal basePrice;
@JsonProperty("MARGIN_FUNDING")
private Integer marginFunding;
@JsonProperty("MARGIN_FUNDING_TYPE")
private Decimal marginFundingType;
@JsonProperty("PL")
private Decimal profitLoss;
@JsonProperty("PL_PERC")
private Decimal profitLossPercentage;
@JsonProperty("PRICE_LIQ")
private Decimal liquidationPrice;
@JsonProperty("LEVERAGE")
private Decimal leverage;
}
我试图解析的这个东西,似乎有一个Position数组,但在它有CHAN_ID之前,我应该为它构造某种包装类吗?
@Getter
@Setter
@EqualsAndHashCode
@ToString
@NoArgsConstructor
public class Positions {
@JsonProperty("CHAN_ID")
private String channelId;
@JsonProperty("positions")
private List<Position> positions;
}
你觉得怎么样,这是对的吗?也不要介意那些顶级类的注释,它只是龙目岛。目前,当我尝试解析时,此实现会给我以下错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException:无法在[Source:(String)“['ps',[['aa','bb',123.45,123.45,567, 123.45,123.45,123.45,123.45,123.45]]]“; line:1,column:1]
为了测试这个我只是使用ObjectMapper:
model.Positions
由于输入JSON的结构是嵌套数组,因此与public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
try {
Positions positions = objectMapper.readValue("['ps', [ [ 'aa', 'bb', 123.45, 123.45, 567, 123.45, 123.45, 123.45, 123.45, 123.45]] ]", Positions.class);
} catch (IOException e) {
e.printStackTrace();
}
}
绑定没有多大意义,因为输入JSON中不存在这些属性键。只有当您想要将反序列化的数据转换为具有属性 - 值对的JSON时,它们才有意义。
要正确读取此JSON结构,您必须实现自定义反序列化器,因为在这种情况下,属性无法自动映射其值。解串器可以是Jackson的@JsonProperty
或JsonDeserializer
的实现。例如,以下实现有效:
StdDeserializer
要使用此反序列化程序,它应该在import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public class PositionsDeserializer extends StdDeserializer<Positions> {
public PositionsDeserializer() {
super(Positions.class);
}
@Override
public Positions deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Object[] positionsProps = p.readValueAs(Object[].class);
if (positionsProps != null && positionsProps.length > 0) {
String chanId = (String) positionsProps[0];
List<Position> positionsList =
((List<List<?>>) positionsProps[1]).stream()
.map(this::deserializePosition)
.collect(Collectors.toList());
Positions positions = new Positions();
positions.setChannelId(chanId);
positions.setPositions(positionsList);
return positions;
}
// decide whether you want to return null, throw an exception or other outcome: depends on the constraints of your data
return null;
}
private Position deserializePosition(List<?> props) {
if (props != null && !props.isEmpty()) {
final Position position = new Position();
position.setSymbol((String) props.get(0));
position.setStatus((String) props.get(1));
position.setAmount((Double) props.get(2));
position.setBasePrice((Double) props.get(3));
position.setMarginFunding((Integer) props.get(4));
position.setMarginFundingType((Double) props.get(5));
position.setProfitLoss((Double) props.get(6));
position.setProfitLossPercentage((Double) props.get(7));
position.setLiquidationPrice((Double) props.get(8));
position.setLeverage((Double) props.get(9));
return position;
}
// decide whether you want to return null, throw an exception or other outcome: depends on the constraints of your data
return null;
}
}
中注册:
ObjectMapper
建议
如果您有可能选择/更改输入JSON的结构,我建议减少嵌套并引入更多传统的KV映射。例如,代表private ObjectMapper initObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Positions.class, new PositionsDeserializer());
objectMapper.registerModule(module);
return objectMapper;
}
@Test
public void deserializePositions() throws IOException {
String json = "[ "ps", [ [ "aa", "bb", 123.45, 123.45, 567, 123.45, 123.45, 123.45, 123.45, 123.45 ] ] ]";
Positions positions = initObjectMapper().readValue(json, Positions.class);
System.out.println(positions);
}
:
Positions
这种方法将允许:
- 降低由与值的数组索引相关的幻数引起的错误风险;
- 简化反序列化:如果保留数组结构,则自动读取
{ "CHAN_ID": "string", "positions": [ // Use the arrays here: [ "aa", "bb", 123.45, 123.45, 567, 123.45, 123.45, 123.45, 123.45, 123.45 ], // OR transform the array into KV mapping: { "SYMBOL": "string", ... }, ... ] }
并仅为Positions
设置自定义反序列化器。
另外,我不知道Position
类型在原始代码中的含义,所以我用Decimal
替换它。
以上是关于用杰克逊解析数组的主要内容,如果未能解决你的问题,请参考以下文章
使用Jackson“意外令牌(START_OBJECT)使用LocalDateTime将JSON解析为POJO,预期VALUE_STRING:预期的数组或字符串。”