jackson注解通过将索引Map到属性来解组数组作为对象

thtygnil  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(433)

我正在阅读一条流,该流提供用于计算市场深度的订单簿的更新。每个都包括一个订单簿的新条目列表。每个条目包含三个属性。
市场方面(如购买或出售)
商品交易量
本次交易商品单价
这些条目在json中表示为数组节点。下面是如何提供条目的示例。

{
    "Changes": [
        { "entry": ["buy","470.84724800000004","16.14963"] },
        { "entry": ["buy","470.787392","0.01"] },
        { "entry": ["sell","473.112752","9.325423"] },
        { "entry": ["sell","473.052608","11.80723"] }
    ],
    ...some more fields; not relevant to this question...
}

如您所见,每个条目数组的索引都用作字段名。每个数组元素的位置定义了它所表示的属性。边在指数0,单价在指数1,数量在指数2。
如何使用java8中的jackson注解对这些数组进行反序列化?我只是问一下最里面的数组。一般来说,我不需要对象结构方面的帮助。
我试着做了一个类似下面的类。

public class OrderBookEntry {
    final String side;
    final BigDecimal price;
    final BigDecimal quantity;

    @JsonCreator
    public OrderBookEntry(@JsonProperty(index = 0, required = true) String side,
                          @JsonProperty(index = 1, required = true) BigDecimal price,
                          @JsonProperty(index = 2, required = true) BigDecimal quantity) {
        this.side = side;
        this.price = price;
        this.quantity = quantity;
    }
}

我试过具体说明 @JsonFormat.Shape.ARRAY 在课堂上。每次尝试反序列化示例字符串时,都会得到一个 InvalidDefinitionException .
线程“main”com.fasterxml.jackson.databind.exc.invaliddefinitionexception中出现异常:
类型com.example.orderbookentry的类型定义无效:参数#0没有属性名,不可注入:不能用作com.example.orderbookentry的创建者[构造函数,注解:{interface com.fasterxml.jackson.annotation]。jsoncreator=@com.fasterxml.jackson.annotation.jsoncreator(mode=default)}]在[source:(string)“[”buy“,"470.84724800000004","16.14963"]"; 行:1,列:1]
难道没有一种方法可以只使用注解来实现这一点吗?

p、 s.(咆哮)

我只想补充一句,这是一个荒谬的数据结构。这毫无意义。使用数组索引而不是对象字段名的目的是减少消息的大小。这是一个金融数据流,对金融数据的网络延迟的任何改进都是可取的。但是,在每个数组周围都有一个完全多余的 Package 器对象和一个命名字段。这会为每个条目添加至少10个字节的不必要流量。数据结构的设计很差。

8fsztsew

8fsztsew1#

有不止一种方法可以做到这一点,但我总是喜欢将专用类与专用序列化程序相结合。其他选择是:
使用objectmapper注册序列化程序–显式编码而不是(元级别)注解
使用一个通用的set方法(使用map<string,object>)–在一个冗长的方法中隐藏序列化程序的方面
用父类中的setterMapjsonnode–如#2
取而代之的是:

@JsonDeserialize(using = OrderBookEntryDeserializer.class)
public class OrderBookEntry {
  // no further Jackson-annotations necessary
}

以及序列化程序:

class OrderBookEntryDeserializer extends StdDeserializer<OrderBookEntry> {
    OrderBookEntryDeserializer() {
        super(OrderBookEntry.class);
    }

    @Override
    public OrderBookEntry deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        final JsonNode node = p.getCodec().readTree(p);
        // now follow Jackson API to turn the node into
        // an ArrayNode, there are plenty of is-methods
        // and it requires a hard cast.
    }

我的示例使用了一个包私有反序列化器类,该类工作得非常好,并将其锁定在包中(最好是紧挨着orderbookentry)。

相关问题