I am reading from a stream that provides updates to an order book used to calculate market depth. Each includes a list of new entries for the order book. Each entry contains three properties.
- Market side (e.g. buy or sell)
- Quantity transacted of the commodity
- Unit price of the commodity in this transaction
These entries are represented in JSON as array nodes. Here is an example of how entries might be provided.
{
"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...
}
As you can see, the indices of each entry array are used as field names. The position of each array element defines what property it represents. The side is at index 0, the unit price is at index 1, and the quantity is at index 2.
How can I de/serialize these using arrays Jackson annotations in Java 8? I am only asking about the innermost arrays. I don't need help with the object structure in general.
I tried making a class similar to the following.
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;
}
}
I have tried specifying @JsonFormat.Shape.ARRAY
on the class. Every time I try to deserialize a sample string, I get an InvalidDefinitionException
.
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Invalid type definition for type com.example.OrderBookEntry: Argument #0 has no property name, is not Injectable: can not use as Creator [constructor for com.example.OrderBookEntry, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] at [Source: (String)"["buy","470.84724800000004","16.14963"]"; line: 1, column: 1]
Is there not a way to do this with only annotations?
P.S. (rant)
I'd just like to add, this is an absurd data structure. It makes no sense. The purpose of using array indices instead of object field names would be to reduce the size of messages. This is a financial data stream, and any improvement to the network latency of financial data is desirable. But, around each of these arrays is a completely superfluous wrapper object with a single named field. This adds at least 10 bytes of unnecessary traffic per entry. The data structure has a very poor design.