emsky
emsky

Reputation: 3

Convert JSON from Elasticsearch to Java Object

I have a problem with gson.fromJson function. I'm getting JSON from my ElasticSearch. I can convert the body to String but I can't convert this to object. Maybe I should use something else then Gson? Can someone help? Thank you in advance.

Get data and gson.fromJson:

 try {
    Response response = restClient.performRequest(
            "GET",
            "/elasticsearch/posts/car/_search",
            Collections.<String, String>emptyMap(),
            entity1);

    String responseBody = EntityUtils.toString(response.getEntity());
    Gson gson = new Gson();
    DataCar dataCar = gson.fromJson(responseBody, DataCar.class);
    GsonBuilder gsonBuilder = new GsonBuilder();
    DataCar cars = gsonBuilder.create().fromJson(responseBody,DataCar.class);
    ArrayList<Car> carsList = cars.getCars();

} catch (IOException e) {
    e.printStackTrace();
}

JSON text:

 {
   "took":1,
   "timed_out":false,
   "_shards":{"total":1,"successful":1,"skipped":0,"failed":0},
   "hits":{"total":{"value":6,"relation":"eq"},
   "max_score":1.0,
   "hits": [{"_index":"posts","_type":"car","
    _id":"b9ZirGoByBAZW2S2ADLS","
   _score":1.0,
    "_source":{
      "image_url": "https://examplepicturelink.com/xyz.jpg",
      "brand": "Audi",
      "model": "A8",
      "price": "120000",
      "engine":"5.0",
      "year":"2018",
      "hp":"380",
      "mileage":"100",
      "color":"czarny",
      "damaged":"false",
      "automated":"true",
      "fuel":"true",
      "country_from":"Polska",
      "post_id":"123abc456d7",
      "url":"https://examplepicturelink.com/xyz.jpg",
      "region":"Kujawsko-pomorskie",
      "city":"Bydgoszcz",
      "description":"Samochód z salonu, bardzo polecam!",
      "created_at":"29-04-2019"
}} // and more records

Downloading data to application work good

DataCar and Car model:

public class DataCar {
public ArrayList<Car> getCars() {
    return cars;
}

public void setCars(ArrayList<Car> cars) {
    this.cars = cars;
}

private ArrayList<Car> cars;
}



import com.google.gson.annotations.SerializedName;

public class Car {

@SerializedName("image_url")
private String image_url;
@SerializedName("brand")
private String brand;
@SerializedName("model")
private String model;
@SerializedName("price")
private Double price;
@SerializedName("engine")
private String engine;
@SerializedName("year")
private Integer year;
@SerializedName("hp")
private Integer hp;
@SerializedName("mileage")
private Integer mileage;
@SerializedName("color")
private String color;
@SerializedName("damaged")
private Boolean damaged;
@SerializedName("automated")
private Boolean automated;
@SerializedName("fuel")
private Boolean fuel;
@SerializedName("country_from")
private String country_from;
@SerializedName("post_id")
private String post_id;
@SerializedName("url")
private String url;
@SerializedName("region")
private String region;
@SerializedName("city")
private String city;
@SerializedName("description")
private String description;
@SerializedName("created_at")
private String created_at;
//getters + setters + constructors
}

Upvotes: 0

Views: 4469

Answers (1)

Sachith Dickwella
Sachith Dickwella

Reputation: 1490

I'd rather use FasterXML/Jackson than "Google Gson" considering its capabilities. You would need following dependecies if you're using Maven to dependency management or add each of the dependecies to your classpath otherwise.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>

For your problem you can try something like this to your POJO.

@JsonInclude(JsonInclude.Include.NON_NULL)  // This will exclude null JSON attributes.
@JsonIgnoreProperties(ignoreUnknown = true) // This will exclude any unknown(not available in the class) attribute in the JSON string.
public class Car {

    @JsonProperty("image_url") // No matter if you didn't use this annotation. Jackson will automatically bind the variable name.
    private String image_url;

    @JsonProperty("brand")
    private String brand;

    @JsonProperty("model")
    private String model;

    @JsonProperty("price")
    private Double price;

    @JsonProperty("engine")
    private String engine;

    @JsonProperty("year")
    private Integer year;

    @JsonProperty("hp")
    private Integer hp;

    @JsonProperty("mileage")
    private Integer mileage;

    @JsonProperty("color")
    private String color;

    // Omitted the rest.
}

To de-serialize the JSON string now you would need a function like this.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.IOException;
import java.util.List;

public class JsonProcessor { // This implementation can change as you want.

    public static <T> List<T> unmarshallToList(String json, Class<T> classType)
            throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        CollectionType javaType = mapper.getTypeFactory() // Check here whether you can take different function to directly de-serialize to the object than to a List.
                .constructCollectionType(List.class, classType);

        return mapper.readValue(json, javaType);
    }
}

When you invoke the unmarshallToList function, you need to pass JSON String and the class type and the function will return List of your objects.

List<Car> cars = JsonProcessor.unmarshallToList(jsonString, Car.class);

If your JSON object doesn't work yet, try wrapping the JSON string with [ ] to imply it as a JSON Array.

If you do any change to unmarshallToList function, you need adjust your JSON string accordingly. Check this documentation to understand what you can do to change the return type of the function.

Upvotes: 2

Related Questions