首页 > 解决方案 > 以数字作为属性名称的 Json 映射

问题描述

我以以下 json 为例:

{
    "success": true,
    "data": {
        "1": {
            "amount": "1"
        },
        "2": {
            "amount": "98"
        }
    }
}

不幸的是,我无法控制传入的 JSON 结构。我一直在尝试找到一种使用 JSONProperties 将这些映射到 DTO 的方法,但是我不能使用数字声明属性。

我也尝试过使用 JSONObject 迭代认为 JSON,但我似乎无法让它通过所有子节点,只是顶层。

JSONObject payload = new JSONObject(jsonString);
JSONObject newPayload = payload;

Iterator<String> keys = payload.keys();

while (keys.hasNext()) {
                String key = keys.next();

                if (StringUtils.isNumber(key)) {
                    newPayload.put("element" + key, payload.get(key));
                    newPayload.remove(key);
                }
}

有没有人遇到过类似的情况并找到了解决方案。

所有这一切最终将 JSON 转换为 XML...继承了这个平台,没有时间重构大声笑,不是我的选择。

标签: javajsonjacksonmappingtransformation

解决方案


有许多解决方案,但假设您只需要反序列化这种病态结构,这就是我的处理方式(Groovy 风格的紧凑性):

class ResponseData {
  Map<String, Long> amounts = new HashMap<>()  // or different key type


  static class WrappedAmount {
    String amount

    Long getAmountAsLong() {
      return Long.valueOf(amount)
    }
  }


  @JsonAnySetter  // this is the magic step
  void appendAmount(String key, WrappedAmount amount) {
    amounts.put(key, amount.getAmountAsLong())
  }
}


class Response {
  boolean success  // REST endpoints should use status codes, not properties
  ResponseData data
}

这会将您的响应反序列化为可管理的数据结构。如果按照您的建议,这些键是索引,并且将被删除并替换为 XML 标记的排序之类的东西,您可能希望替换HashMap为,TreeMap以便您可以迭代它以生成输出。


推荐阅读