如何有效地将 org.json.JSONObject 映射到 POJO? [英] How to efficiently map a org.json.JSONObject to a POJO?

查看:27
本文介绍了如何有效地将 org.json.JSONObject 映射到 POJO?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题以前肯定有人问过,但我找不到.

This question must have been asked before, but I couldn't find it.

我正在使用第 3 方库来检索 JSON 格式的数据.该库将数据作为 org.json.JSONObject 提供给我.我想将此 JSONObject 映射到 POJO(Plain Old Java Object) 更简单的访问/代码.

I'm using a 3rd party library to retrieve data in JSON format. The library offers the data to me as a org.json.JSONObject. I want to map this JSONObject to a POJO (Plain Old Java Object) for simpler access/code.

对于映射,我目前以这种方式使用 Jackson 库中的 ObjectMapper:

For mapping, I currently use the ObjectMapper from the Jackson library in this way:

JSONObject jsonObject = //...
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(jsonObject.toString(), MyPojoClass.class);

据我所知,上面的代码可以得到显着的优化,因为当前 JSONObject 中的数据已经被解析,再次被送入带有 JSONObject 的序列化-反序列化链.toString() 方法,然后到 ObjectMapper.

To my understanding, the above code can be optimized significantly, because currently the data in the JSONObject, which is already parsed, is again fed into a serialization-deserialization chain with the JSONObject.toString() method and then to the ObjectMapper.

我想避免这两种转换(toString() 和解析).有没有办法使用 JSONObject 将其数据直接映射到 POJO?

I want to avoid these two conversions (toString() and parsing). Is there a way to use the JSONObject to map its data directly to a POJO?

推荐答案

因为你有一些 JSON 数据的抽象表示(一个 org.json.JSONObject 对象)并且您计划使用 Jackson 库 - 它有自己的 JSON 数据抽象表示(com.fasterxml.jackson.databind.JsonNode) - 那么从一种表示到另一种表示的转换将使您免于解析-序列化-解析过程.因此,不是使用接受 StringreadValue 方法,而是使用 这个版本接受一个 JsonParser:

Since you have an abstract representation of some JSON data (an org.json.JSONObject object) and you're planning to use the Jackson library - that has its own abstract representation of JSON data (com.fasterxml.jackson.databind.JsonNode) - then a conversion from one representation to the other would save you from the parse-serialize-parse process. So, instead of using the readValue method that accepts a String, you'd use this version that accepts a JsonParser:

JSONObject jsonObject = //...
JsonNode jsonNode = convertJsonFormat(jsonObject);
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(new TreeTraversingParser(jsonNode), MyPojoClass.class);

JSON 是一种非常简单的格式,因此手动创建 convertJsonFormat 应该不难.这是我的尝试:

JSON is a very simple format, so it should not be hard to create the convertJsonFormat by hand. Here's my attempt:

static JsonNode convertJsonFormat(JSONObject json) {
    ObjectNode ret = JsonNodeFactory.instance.objectNode();

    @SuppressWarnings("unchecked")
    Iterator<String> iterator = json.keys();
    for (; iterator.hasNext();) {
        String key = iterator.next();
        Object value;
        try {
            value = json.get(key);
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        if (json.isNull(key))
            ret.putNull(key);
        else if (value instanceof String)
            ret.put(key, (String) value);
        else if (value instanceof Integer)
            ret.put(key, (Integer) value);
        else if (value instanceof Long)
            ret.put(key, (Long) value);
        else if (value instanceof Double)
            ret.put(key, (Double) value);
        else if (value instanceof Boolean)
            ret.put(key, (Boolean) value);
        else if (value instanceof JSONObject)
            ret.put(key, convertJsonFormat((JSONObject) value));
        else if (value instanceof JSONArray)
            ret.put(key, convertJsonFormat((JSONArray) value));
        else
            throw new RuntimeException("not prepared for converting instance of class " + value.getClass());
    }
    return ret;
}

static JsonNode convertJsonFormat(JSONArray json) {
    ArrayNode ret = JsonNodeFactory.instance.arrayNode();
    for (int i = 0; i < json.length(); i++) {
        Object value;
        try {
            value = json.get(i);
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        if (json.isNull(i))
            ret.addNull();
        else if (value instanceof String)
            ret.add((String) value);
        else if (value instanceof Integer)
            ret.add((Integer) value);
        else if (value instanceof Long)
            ret.add((Long) value);
        else if (value instanceof Double)
            ret.add((Double) value);
        else if (value instanceof Boolean)
            ret.add((Boolean) value);
        else if (value instanceof JSONObject)
            ret.add(convertJsonFormat((JSONObject) value));
        else if (value instanceof JSONArray)
            ret.add(convertJsonFormat((JSONArray) value));
        else
            throw new RuntimeException("not prepared for converting instance of class " + value.getClass());
    }
    return ret;
}

请注意,虽然 Jackson 的 JsonNode 可以表示一些额外的类型(例如 BigIntegerDecimal 等),但它们不是必需的,因为上面的代码涵盖了 JSONObject 可以表示的所有内容.

Note that, while the Jackson's JsonNode can represent some extra types (such as BigInteger, Decimal, etc) they are not necessary since the code above covers everything that JSONObject can represent.

这篇关于如何有效地将 org.json.JSONObject 映射到 POJO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆