Reputation: 7400
Is there a Jackson annotation that will allow an array to be deserialized into specific fields of my POJO? I can easily do this with a custom deserializer, but I was hoping to get this done in-line with the class.
For example, I have the following JSON coming back from Elasticsearch.
{
"_index": "twitter",
"_type": "tweet",
"_id": "AVodOsgk0etILSbJamY-",
"_score": null,
"_source": {
"tweetText": "I'm at Residencial Nova Alegria https:\/\/t.co\/4TyK8PAWzB",
"placeCountry": "Brasil",
"screenName": "wildelson",
"cleanedText": "I'm at Residencial Nova Alegria https:\/\/t.co\/4TyK8PAWzB",
"resolvedUrls": [
"https:\/\/www.swarmapp.com\/c\/gfULJdQ6umw"
],
"tweetId": "829272906291085314",
"tweetDate": 1486549042000
},
"sort": [
1486549042000,
"tweet#AVodOsgk0etILSbJamY-"
]
}
My POJO as follows:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder(value = {
"enrichedStatus",
"sortValue",
"uid"
})
public class TweetHit {
private final EnrichedStatus enrichedStatus;
private final Long sortValue;
private final String uid;
public TweetHit(EnrichedStatus enrichedStatus, Long sortValue, String uid) {
this.enrichedStatus = enrichedStatus;
this.sortValue = sortValue;
this.uid = uid;
}
I want the "sort" array, which will always have a long in array[0] and a String in array[1], to be deserialized as follows:
Long sortValue = sort[0]
String uid = sort[1]
I've found one other question, where the only answer was a custom deserializer, which I would like to avoid if I can. Jackson: Deserialize JSON-Array in different attributes of an object
I thought perhaps I can use @JsonProperty("sort")
with @JsonFormat(shape = ARRAY)
somehow, but I don't see anyway to specify the specific cell to deserialize into each field.
Note, this is an immutable object and so I likely need the solution to work in-line with the constructor, though maybe I can remove final, add an empty constructor, put the annotations at the field level and use Lombok to disable the setters if Jackson can set directly into the fields?
Upvotes: 6
Views: 2653
Reputation: 22254
You can approach this with the @JsonCreator
and @JsonProperty
annotations and a custom constructor. Since I don't know what class EnrichedStatus
looks like I simplified your example with just the sort
array:
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
@Data
class TweetHit {
private final Long sortValue;
private final String uid;
@JsonCreator
public TweetHit(@JsonProperty("sort") String[] sort) {
this.sortValue = Long.parseLong(sort[0]);
this.uid = sort[1];
}
}
public class StackOverflow {
public static void main(String[] args) throws IOException {
String json = "{ \"sort\": [\n" +
" 1486549042000,\n" +
" \"tweet#AVodOsgk0etILSbJamY-\"\n" +
" ]\n" +
" }";
ObjectMapper objectMapper = new ObjectMapper();
TweetHit tweetHit = objectMapper.readValue(json, TweetHit.class);
}
}
This preserves immutability of TweetHit
class and avoids a custom deserializer.
I can't see a way to do this with a @JsonFormat(shape = ARRAY)
that serves a different purpose. Even if it was possible I doubt it would be simpler than a constructor that takes the array and assigns it's content to fields.
Also check this answer if you'd also like to avoid @JsonCreator
, @JsonProperty
annotations.
Upvotes: 2