Home>

Hello everyone! I am recently learning Java, please do not scold me too much for a possibly stupid question. My task is to get the current exchange rate from a remote API server (then I will need to do a few more actions with the result, but the essence of this topic is different). The response from the server comes in the following format:

{
disclaimer: "https://openexchangerates.org/terms/",
license: "https://openexchangerates.org/license/",
timestamp: 1449877801,
base: "USD",
rates: {
    AED: 3.672538,
    AFN: 66.809999,
    ALL: 125.716501,
    AMD: 484.902502,
    ANG: 1.788575,
    AOA: 135.295998,
    ARS: 9.750101,
    AUD: 1.390866,
    /* ... * /
    }
}

The number of currencies, as you understand, is large (more than a hundred items). The application itself must be written in Spring Boot 2, the Gradle collector. Feign is used to interact with external services. I do not understand how my classes (models) should look like to parse such JSON. At the moment, the code looks like this:

Service:

@FeignClient (name= "Rate", url= "https://openexchangerates.org/api")
public interface RateService {
    @GetMapping ("/latest.json")
    RateMainJSON getAllLatestRates (@RequestParam String app_id);
}

Controller:

@RestController
@EnableAutoConfiguration
@RequestMapping ("/")
public class RateController {
    private static final String APP_ID= "1ce73ad6a57744ba8514dd76d877b297";
    @Autowired
    private RateService rateService;
    @GetMapping ("latest.json")
    RateMainJSON getAllLatestRates (@RequestParam String app_id) {
        RateMainJSON rates= rateService.getAllLatestRates (APP_ID);
        return rates;
    }
}

A class (model) that includes all lines of the general structure of the received JSON:

public class RateMainJSON {
    @JsonProperty ("disclaimer")
    private String disclaimer;
    @JsonProperty ("license")
    private String license;
    @JsonProperty ("timestamp")
    private Long timestamp;
    @JsonProperty ("base")
    private String base;
    @JsonProperty ("rates")
    private Rate rates;
}

and a class (model), which in my implementation is able to recognize only one type of currency "RUB":

public class Rate {
@JsonProperty ("RUB")
private BigDecimal RUB;
public Rate () {
}

Also tried to create only one Map field in this class < String, BigDecimal > but was just getting null instead of a list of currencies.

As a result of all my code, I get the following output:

{
"disclaimer": "Usage subject to terms: https://openexchangerates.org/terms",
"license": "https://openexchangerates.org/license",
"timestamp": 1614009600,
"base": "USD",
"rates": {
    "RUB": 74.384
    }
}

But, as you can imagine, I need the entire list of currencies. Of course, I can list all existing currencies in the Rate class, but then there will be more than 100 fields in it, plus if a currency is added or removed on the site, then my application will not react to it. There must be some concise way. Also, I would like to get rid of the RateMainJSON class, since I don't need the disclaimer, license, timestamp, base, rates lines at all.

It seems that the question is elementary (to parse JSON), but I've been working on various resources for a couple of days and can't find a way to parse it.

Thanks in advance if someone can direct my train of thought in the right direction.

I would try private Rate rates instead; use private Map rates

tym321672021-02-24 09:16:11

everything has long been invented before us, use this service and form classes -jsonschema2pojo.org

AlekseiGaile2021-02-24 09:16:11

@ tym32167 Yes, I tried, but then I get "There was an unexpected error (type= Internal Server Error, status= 500)."

MShkolniy2021-02-24 09:16:11

@AlekseiGaile Thanks for the service, I didn't know it was possible. Now I tried my JSON there, but the service produces a POJO, which lists all possible currencies. Do you know a way to avoid such a large enumeration of fields in a class? Well, as I already wrote in the post -if a currency is added or removed on the site, then my application will not track it and errors are possible. Is there some other more versatile way?

MShkolniy2021-02-24 09:16:11

baelding.com /yatskson-map

AlekseiGaile2021-02-24 09:16:11