Brooks
Brooks

Reputation: 7400

Jackson deserialize array elements into specific fields

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

Answers (1)

Manos Nikolaidis
Manos Nikolaidis

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

Related Questions