我有一个JSON示例
{
"data":"some string data",
"amount":200,
"amountCurrencyList":[
{"value":4000.0,"currency":"USD"},
{"value":100.0,"currency":"GBP"}
]
}
和当前将其解析为基础对象的地图字段的方法
public void buildDetailsFromJson(String details) {
if (details != null) {
TypeReference<HashMap<String, Object>> mapTypeReference = new TypeReference<HashMap<String, Object>>() {
};
ObjectMapper mapper = new ObjectMapper();
try {
mapper.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
mapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);
detailsMap = mapper.readValue(details, mapTypeReference);
} catch (IOException e) {
log.error("Exception during JSON {} parsing! {}", details, e.getMessage());
}
}
}
JSON结构可以更改。
想法是有一个单独的方法,理想情况下可以像map.get(key_name)
例如
public void setUpFieldsFromMap() {
HashMap<String, Object> map = super.detailsMap;
this.amountCurrencyList = (ArrayList<MoneyValue>) map.get("amountCurrencyList");
if (isNull(amountCurrencyList)) {
throw new InvalidOrMissingParametersException("Exception during JSON parsing! Critical data is missing in DetailsMap - " + map.toString());
}
}
因此,通过键获取List对象并将其强制转换为所需的参数。
但是当我尝试使用List<MoneyValue>
System.out.println(detailsObj.getAmountCurrencyList().get(0).getValue());
我要
Exception: java.util.LinkedHashMap cannot be cast to MoneyValue
实际上可以不用像TypeReference<HashMap<String, List<MoneyValue>>>
这样的精确参数对TypeReference进行硬编码吗?
UPD
public class MoneyValue {
@NotNull
private BigDecimal value;
@NotNull
private String currency;
EventDetails类
public class SomeEventDetails extends BaseEventDetails implements EventDetails {
private ArrayList<MoneyValue> amountCurrencyList;
@Override
public void setUpFieldsFromMap() {
HashMap<String, Object> map = super.detailsMap;
this.amountCurrencyList = (ArrayList<MoneyValue>) map.get("amountCurrencyList");
if (isNull(amountCurrencyList)) {
throw new InvalidOrMissingParametersException("Exception during JSON parsing! Critical data is missing in DetailsMap - " + map.toString());
}
}
}
答案 0 :(得分:0)
如果一组属性(我的意思是输入数据的结构)不可修改,我们可以将其表示为POJO类。设为DetailsData
:
public class DetailsData {
private String data;
private BigDecimal amount;
private List<MoneyValue> amountCurrencyList;
/*getters, setters, constructors*/
public DetailsData() {
}
@JsonProperty("amountCurrencyList")
private void deserializeMoneyValue(List<Map<String, Object>> data) {
if (Objects.isNull(amountCurrencyList)) {
amountCurrencyList = new ArrayList<>();
} else {
amountCurrencyList.clear();
}
MoneyValue moneyValue;
for (Map<String, Object> item : data) {
moneyValue = new MoneyValue(getValue(item.get("value")),
(String) item.get("currency"));
amountCurrencyList.add(moneyValue);
}
}
private BigDecimal getValue(Object value) {
BigDecimal result = null;
if (value != null) {
if (value instanceof BigDecimal) {
result = (BigDecimal) value;
} else if (value instanceof BigInteger) {
result = new BigDecimal((BigInteger) value);
} else if (value instanceof Number) {
result = new BigDecimal(((Number) value).doubleValue());
} else {
throw new ClassCastException("Invalid value");
}
}
return result;
}
}
如您所见,这里有一个方法deserializeMoneyValue
注释为JSON属性。因此,对于ObjectMapper,它将用作自定义反序列化器。 getValue
方法是必需的,因为Jackson的工作方式是这样,以便在满足该值大小的类中将值反序列化。例如如果值=“ 100”,它将反序列化为Integer
,如果值=“ 100.0”,则反序列化为Double
,依此类推。实际上,您可以使用此方法制作static
并进入某些util类。
总结一下,您可以按照以下方式更改buildDetailsFromJson
:
public void buildDetailsFromJson(String details) {
if (details != null) {
ObjectMapper mapper = new ObjectMapper();
try {
mapper.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
mapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);
// assuming the eventDetails is an instance of DetailsData
eventDetails = mapper.readValue(details, DetailsData.class);
} catch (IOException e) {
log.error("Exception during JSON {} parsing! {}", details, e.getMessage());
}
}
}
和EventDetail类:
public class SomeEventDetails extends BaseEventDetails implements EventDetails {
private List<MoneyValue> amountCurrencyList;
@Override
public void setUpFieldsFromMap() {
this.amountCurrencyList = super.eventDetails.getAmountCurrencyList();
if (isNull(amountCurrencyList)) {
throw new InvalidOrMissingParametersException("Exception during JSON parsing! Critical data is missing in DetailsMap - " + super.eventDetails.toString());
}
}
}