使用Jackson将关联数组请求参数转换为JSON

时间:2016-06-06 14:10:44

标签: json spring jackson

我是一个看起来像这样的webhook POST的接收者,为了便于阅读,我已经解码了。

id=12345&event=this_event&payload[customer][name]=ABC Company&payload[customer][city]=New York&payload[service][name]=New Customer&payload[service][action]=New

使用Spring MVC,我可以轻松地将其转换为Map<String, Sting>,看起来像这样

{id=97659204, event=test, payload[customer][name]=ABC Company, payload[customer][city]=New York, payload[service][name]=New Customer, payload[service][action]=New}

我需要将以“payload”开头的每个参数(或Map键)解析为JSON对象。

我解析以“payload”开头的请求参数所需的输出看起来像这样

{
    customer :  {
        name : "ABC Company",
        city : "New York"
    },
    service : {
        name : "New Customer",
        action : "New"
    }
}

最终状态是调用Jackson的ObjectMapper将JSON变成POJO。

由于我无法控制开始发送给我的数据格式,将这些请求参数解析为JSON对象的最佳/正确选项是什么?

感谢。

1 个答案:

答案 0 :(得分:0)

我最后为传入的payload [] [] []参数编写了一个自定义解析器。它使用正则表达式匹配器然后递归来分析每个参数,遍历1 ... n的地图然后生成地图制作完美的JSON。

@RequestMapping(value = "/receiver", method = RequestMethod.POST)
@ResponseBody
public void receiver(@RequestParam Map<String, Object> requestBody) throws IOException {

    Pattern pattern = Pattern.compile("\\[([^\\]]+)]");

    Map<String, Object> payloadMap = new HashMap<>();
    Matcher matcher = null;
    List<String> levels = null;

    for (String key : requestBody.keySet()) {

        if (key.startsWith("payload")) {

            matcher = pattern.matcher(key);
            levels = new ArrayList<>();
            while (matcher.find()) {
                levels.add(matcher.group(1));
            }

            payloadMap = nestMap(payloadMap, levels.iterator(), (String) requestBody.get(key));

        }
    }

    LOG.debug(mapper.writeValueAsString(payloadMap));

}

@SuppressWarnings("unchecked")
private Map<String, Object> nestMap(Map<String, Object> baseMap, Iterator<String> levels, String value) {

    String key = levels.next();

    if (!levels.hasNext()) {
        baseMap.put(key, value);
    } else {
        if (!baseMap.containsKey(key)) {
            baseMap.put(key, nestMap(new HashMap<String, Object>(), levels, value));
        } else {
            baseMap.put(key, nestMap((Map<String, Object>) baseMap.get(key), levels, value));
        }
    }

    return baseMap;

}