如何有效地将org.json.JSONObject映射到POJO?

时间:2013-12-12 04:07:24

标签: java json mapping jackson mapper

之前一定要问过这个问题,但我找不到了。

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

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

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

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

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

4 个答案:

答案 0 :(得分:25)

由于您有一些JSON数据的抽象表示(org.json.JSONObject对象),并且您计划使用Jackson库 - 它有自己的JSON数据的抽象表示(com.fasterxml.jackson.databind.JsonNode) - 然后从一个表示转换到另一个表示将使您免于parse-serialize-parse过程。因此,您不是使用接受readValue的{​​{1}}方法,而是使用接受String的{​​{3}}:

JsonParser

JSON是一种非常简单的格式,因此手动创建JSONObject jsonObject = //... JsonNode jsonNode = convertJsonFormat(jsonObject); ObjectMapper mapper = new ObjectMapper(); MyPojoClass myPojo = mapper.readValue(new TreeTraversingParser(jsonNode), MyPojoClass.class); 并不困难。这是我的尝试:

convertJsonFormat

请注意,虽然杰克逊的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; } 可以代表一些额外的类型(例如JsonNodeBigInteger等),但它们不是必需的,因为上面的代码涵盖{{1可以代表。

答案 1 :(得分:24)

如果你没有与杰克逊并列,你可以使用方便的google-gson库作为替代方案。它只需要一个罐子,使用起来非常简单:

将java对象转换为JSON字符串:

  String json_string = new Gson().toJson(an_object);

从JSON字符串创建java对象:

  MyObject obj = new Gson().fromJson(a_json_string, MyObject.class);

与杰克逊相比,我不了解性能,但它很难比这简单...... Gson是一个稳定且广泛使用的库。

请参阅https://code.google.com/p/google-gson/

答案 2 :(得分:12)

添加旧问题的答案,但......

杰克逊可以绑定到org.json类型。通常,它可以在它可以绑定的任何类型之间进行转换,通过有效地(尽管实际上并非实际上)序列化为JSON并反序列化。

如果你注册了JsonOrgModule,你可以直接从ObjectMapper进行转换:

@Test
public void convert_from_jsonobject() throws Exception {
    JSONObject obj = new JSONObject().put("value", 3.14);
    ObjectMapper mapper = new ObjectMapper().registerModule(new JsonOrgModule());
    PojoData data = mapper.convertValue(obj, PojoData.class);
    assertThat(data.value, equalTo(3.14));
}

@Test
public void convert_to_jsonobject() throws Exception {
    PojoData data = new PojoData();
    data.value = 3.14;
    ObjectMapper mapper = new ObjectMapper().registerModule(new JsonOrgModule());
    JSONObject obj = mapper.convertValue(data, JSONObject.class);
    assertThat(obj.getDouble("value"), equalTo(3.14));
}

public static final class PojoData {
    public double value;
}

我提到这是有效序列化?这是真的,它将输入对象序列化为TokenBuffer,它表示JSON解析事件的流,但是构建字符串等的影响较小,因为它可以在很大程度上引用来自输入的数据。然后它将此流提供给反序列化器以生成输出对象。

因此,它有点类似于将JSONObject转换为JsonNode的建议,但更为一般。它是否实际上更高效还需要测量:要么将JsonNode构造为中间体,要么构造TokenBuffer,这两种方式都没有开销。

答案 3 :(得分:1)

使用Gson的更简单方法。

JSONObject jsonObject = //...

PojoObject objPojo = new Gson().fromJson(jsonObject.toString(), PojoObject.class);

这对我有用。