How to create a domain object from a Json element?

520 Views Asked by At

the external web service returns me a Json file of the form {"forecasts":[{"period_end":"2021-01-15T01:00:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0},{"period_end":"2021-01-15T01:30:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0},{"period_end":"2021-01-15T02:00:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0}]}

Using RestRespone a transform an json element

RestResponse resp = rest.get(url)

  resp.json instanceof JsonElement
   

How can I create a domain object from the Json element variable, knowing that my wrapper class is

class ForecastGhi {

static constraints = {
}

private ArrayList<IrradianciaGlobalHorizontal> forecast


ArrayList<IrradianciaGlobalHorizontal> getForecast() {
    return forecast
}

void setForecast(ArrayList<IrradianciaGlobalHorizontal> forecast) {
    this.forecast = forecast
}

}

and de persist domain class is

class IrradianciaGlobalHorizontal {

static constraints = {
}
@JsonProperty("all")  

private def period_end
private def period
private def ghi90
private def ghi
private def ghi10

def getGhi() {
     this.ghi
}

void setGhi(int ghi) {
    this.ghi = ghi
}

def getGhi90() {
    this.ghi90
}

void setGhi90(int ghi90) {
    this.ghi90 = ghi90
}

def getGhi10() {
    this.ghi10
}

void setGhi10(int ghi10) {
    this.ghi10 = ghi10
}

def getPeriod_end() {
     this.period_end
}

void setPeriod_end(Date period_end) {
    this.period_end = period_end
}

def getPeriod() {
    this.period
}

void setPeriod(String period) {
    this.period = period
}

}

Help please; thanks a lot

2

There are 2 best solutions below

1
On

This is an issue with your API implementation; The endpoint changed the domain field names &/or domain name. This will cause issues with bringing said data back in.

Either that or front-end is not matching the API docs for the endpoint.

Field names/domain names should match the domain/resource unless you are going for a level of obfuscation and then accept that you are going to need a middle layer to act as a translater (ie EDI).

You want output to be able to be read as input by the same endpoint by merely changing the request method.

My suggestion (easiest solution): change original endpoint to match domain/resource field names

0
On

If you have the opportunity to use Jackson library, you can do this:

ForecastGhi request = objectMapper.readValue(jsonAsText, ForecastGhi.class);

Create an objectMapper and configure to fail in case of unknown properties (just in case)

private String getJsonAsTextFromRest() {
        String message = " {\"forecasts\":[{\"period_end\":\"2021-01-15T01:00:00.0000000Z\",\"period\":\"PT30M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0},{\"period_end\":\"2021-01-15T01:30:00.0000000Z\",\"period\":\"PT31M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0},{\"period_end\":\"2021-01-15T02:00:00.0000000Z\",\"period\":\"PT32M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0}]}";
        return message;
    }

 @Override
    public void run(String... arg0) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        String jsonAsText = getJsonAsTextFromRest();
        ForecastGhi request = objectMapper.readValue(jsonAsText, ForecastGhi.class);
        request.getForecast().stream().forEach(it -> System.out.println(it.getPeriod() + " " + it.getGhi()));
        
    }

public class IrradianciaGlobalHorizontal {
    private Date period_end;
    private String period;
    private int ghi90;
    private int ghi;
    private int ghi10;

    public int getGhi() {
        return this.ghi;
    }

    public void setGhi(int ghi) {
        this.ghi = ghi;
    }

    public  int getGhi90() {
        return this.ghi90;
    }

    public void setGhi90(int ghi90) {
        this.ghi90 = ghi90;
    }

    public int getGhi10() {
        return this.ghi10;
    }

    void setGhi10(int ghi10) {
        this.ghi10 = ghi10;
    }

    public Date getPeriod_end() {
        return this.period_end;
    }

    public void setPeriod_end(Date period_end) {
        this.period_end = period_end;
    }

    public String getPeriod() {
        return this.period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }
}

ForecastGhi class.

import com.fasterxml.jackson.annotation.JsonProperty;

public class ForecastGhi {

    private ArrayList<IrradianciaGlobalHorizontal> forecast;

    @JsonProperty("forecasts")//It must be the same as the json property
    public ArrayList<IrradianciaGlobalHorizontal> getForecast() {
        return forecast;
    }

    @JsonProperty("forecasts")
    public void setForecast(ArrayList<IrradianciaGlobalHorizontal> forecast) {
        this.forecast = forecast;
    }

}

Results:

  • PT30M 0
  • PT31M 0
  • PT32M 0

Dependencies Gradle:

  compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1'

Or

Dependencies Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.12.1</version>
</dependency>

Note: in your json example you use forecasts, but your java property name is forecast. In that case its necessary to decorate the property with @JsonProperty("forecasts"). If you dont do it, you get an error like this com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "forecasts"