Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 227
Brooks Avatar asked Oct 29 '22 12:10

Brooks


1 Answers

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.

like image 81
Manos Nikolaidis Avatar answered Nov 09 '22 11:11

Manos Nikolaidis