Reputation: 1420
In my elasticsearch cluster I have a document that looks like this:
{
"@version":"1",
"@timestamp":"2021-04-12T14:50:40.298Z",
"message":"{\"@class\": \"com.foobar.PriceChangeEvent\", \"price\":\"4.65\", \"currency\":\"GBP\", \"product\": \"1209381842\", \"meta\": {\"user\": \"TomScott\", \"service\": \"price-manager\"}}",
"exchange":"PriceIncrease",
"service":"price-manager",
"env":"test",
"type":"event",
"user":"TomScott"
}
And a class with the following:
@JsonIgnoreProperties(ignoreUnknown = true)
public class ElasticsearchEventEntry<T extends BaseEvent> {
@JsonProperty("service")
private String service;
@JsonProperty("@timestamp")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime timestamp;
@JsonProperty("env")
private String environment;
@JsonProperty("exchange")
private String exchange;
@JsonProperty("message")
private T event;
@JsonProperty("user")
private String user;
}
Being read using the current method:
ElasticsearchEventEntry<PriceChangeEvent> entry = mapper.readValue(elasticResponse, new TypeReference<ElasticsearchEventEntry<PriceChangeEvent>>() {});
However the message is not parsed straight into a PriceChangeEvent
which is understandable as it's a string not "proper" JSON. I have tried to implement a custom deserialiser which would be able to convert the JSON to the event without any luck.
I've attempted to create a custom deserialiser however it's not working with the polymorphic type.
Upvotes: 1
Views: 552
Reputation: 1420
I finally got the custom deserialiser to work for me:
public class ElasticsearchEventMessageDeserialiser extends JsonDeserializer<BaseEvent> {
@Override
public BaseEvent deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
TextNode textNode = jsonParser.readValueAsTree();
ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
return mapper.readValue(textNode.textValue(), BaseEvent.class);
}
}
And simply annotated the field with the new deserialiser:
@JsonIgnoreProperties(ignoreUnknown = true)
public class ElasticsearchEventEntry<T extends BaseEvent> {
@JsonProperty("service")
private String service;
@JsonProperty("@timestamp")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime timestamp;
@JsonProperty("env")
private String environment;
@JsonProperty("exchange")
private String exchange;
@JsonProperty("message")
@JsonDeserialize(using = ElasticsearchEventMessageDeserialiser.class)
@JsonTypeInfo(use = Id.NONE)
private T event;
@JsonProperty("user")
private String user;
}
Upvotes: 1