I would like create a Java object which map this JSON object:
{
"base_currency_code": "HKD",
"base_currency_name": "Hong Kong dollar",
"amount": "150.5800",
"updated_date": "2022-03-20",
"rates": {
"GBP": {
"currency_name": "Pound sterling",
"rate": "0.0975",
"rate_for_amount": "14.6774"
}
},
"status": "success"
}
Only the "GBP"
property name is dynamic field, it could be another currency symbol next time like "USD"
, "JPY"
etc.
I create the Java class like this:
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"base_currency_code",
"base_currency_name",
"amount",
"updated_date",
"rates",
"status"
})
public class CurrencyConvertDto {
@JsonProperty("base_currency_code")
private String baseCurrencyCode;
@JsonProperty("base_currency_name")
private String baseCurrencyName;
@JsonProperty("amount")
private String amount;
@JsonProperty("updated_date")
private String updatedDate;
@JsonProperty("rates")
private Rates rates;
@JsonProperty("status")
private String status;
/*
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
*/
@JsonProperty("base_currency_code")
public String getBaseCurrencyCode() {
return baseCurrencyCode;
}
@JsonProperty("base_currency_code")
public void setBaseCurrencyCode(String baseCurrencyCode) {
this.baseCurrencyCode = baseCurrencyCode;
}
@JsonProperty("base_currency_name")
public String getBaseCurrencyName() {
return baseCurrencyName;
}
@JsonProperty("base_currency_name")
public void setBaseCurrencyName(String baseCurrencyName) {
this.baseCurrencyName = baseCurrencyName;
}
@JsonProperty("amount")
public String getAmount() {
return amount;
}
@JsonProperty("amount")
public void setAmount(String amount) {
this.amount = amount;
}
@JsonProperty("updated_date")
public String getUpdatedDate() {
return updatedDate;
}
@JsonProperty("updated_date")
public void setUpdatedDate(String updatedDate) {
this.updatedDate = updatedDate;
}
@JsonProperty("rates")
public Rates getRates() {
return rates;
}
@JsonProperty("rates")
public void setRates(Rates rates) {
this.rates = rates;
}
@JsonProperty("status")
public String getStatus() {
return status;
}
@JsonProperty("status")
public void setStatus(String status) {
this.status = status;
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Rates {
private List<Map<String, String>> rateInfo = new ArrayList<Map<String, String>>();
@JsonAnySetter
public void setDynamicProperty(String name, Map<String, String> map) {
rateInfo.add(map);
}
public List<Map<String, String>> getRateInfo() {
return rateInfo;
}
public void setRateInfo(List<Map<String, String>> rateInfo) {
this.rateInfo = rateInfo;
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"currency_name",
"rate",
"rate_for_amount"
})
public class RateInfo {
@JsonProperty("currency_name")
private String currencyName;
@JsonProperty("rate")
private String rate;
@JsonProperty("rate_for_amount")
private String rateForAmount;
/*
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
*/
@JsonProperty("currency_name")
public String getCurrencyName() {
return currencyName;
}
@JsonProperty("currency_name")
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
}
@JsonProperty("rate")
public String getRate() {
return rate;
}
@JsonProperty("rate")
public void setRate(String rate) {
this.rate = rate;
}
@JsonProperty("rate_for_amount")
public String getRateForAmount() {
return rateForAmount;
}
@JsonProperty("rate_for_amount")
public void setRateForAmount(String rateForAmount) {
this.rateForAmount = rateForAmount;
}
}
But when compile, it seems have problem. it can't map the JSON object with the dynamic field . Does anyone know how to fix it? Thanks you very much.
CodePudding user response:
You can use @JsonAnyGetter and get the additional dynamic key value pair(s) in a Map. Please refer to the usage of @JsonAnyGetter in the following example and do let me know if you still need help.
https://www.logicbig.com/tutorials/misc/jackson/jackson-any-setter.html
CodePudding user response:
May be you were thinking too complicated here.
In your CurrencyConvertDto
class, instead of using
@JsonProperty("rates")
private Rates rates;
you can simply use
@JsonProperty("rates")
private Map<String, RateInfo> rates;
(and of course adjust the getRates
and setRates
methods accordingly).
And then you don't need the Rates
class anymore.
Jackson can cope with this out-of-the-box, even if you might have more rates in the future, like in:
{
"base_currency_code": "HKD",
"base_currency_name": "Hong Kong dollar",
"amount": "150.5800",
"updated_date": "2022-03-20",
"rates": {
"GBP": {
"currency_name": "Pound sterling",
"rate": "0.0975",
"rate_for_amount": "14.6774"
},
"EUR": {
"currency_name": "Euro",
"rate": "0.120",
"rate_for_amount": "18.07"
}
},
"status": "success"
}
And by the way: You don't need to repeat the @JsonProperty
annotations on the getter and setter methods. Putting @JsonProperty
only on the member variables is already enough.
CodePudding user response:
If you are able, the simplest option would be to use a reasonable JSON design.
Here is an example:
{
"base_currency_code": "HKD",
"base_currency_name": "Hong Kong dollar",
"amount": "150.5800",
"updated_date": "2022-03-20",
"rates": {
"currentySymbol": "GBP",
"currency_name": "Pound sterling",
"rate": "0.0975",
"rate_for_amount": "14.6774"
}
},
"status": "success"
}