为了账号安全,请及时绑定邮箱和手机立即绑定

解析 JSON 的通用方法

解析 JSON 的通用方法

慕森卡 2021-11-24 14:37:39
我有一个 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 进行硬编码TypeReference<HashMap<String, List<MoneyValue>>>?UPDpublic class MoneyValue {@NotNullprivate BigDecimal value;@NotNullprivate String currency;EventDetails 类public class SomeEventDetails extends BaseEventDetails implements EventDetails {private ArrayList<MoneyValue> amountCurrencyList;
查看完整描述

1 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

如果一组属性(我的意思是输入数据的结构)是不可修改的,我们可以将它表示为一个 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 以这种方式工作,因此值将在满足值大小的类中反序列化。例如,如果 value = "100" 它将被反序列化为Integer,如果 value = "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());

        }

    }

}


查看完整回答
反对 回复 2021-11-24
  • 1 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信