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

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

我正在使用第三方库来检索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?

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

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

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

 static JsonNode convertJsonFormat(JSONObject json) { ObjectNode ret = JsonNodeFactory.instance.objectNode(); @SuppressWarnings("unchecked") Iterator 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可以表示的所有内容。

如果你没有与jackson联系,你可以使用方便的google-gson库作为替代方案。 它只需要一个jar子,使用起来非常简单:

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

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

从JSON字符串创建java对象:

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

与jackson相比,我不知道性能,但是比这更难简单… Gson是一个稳定且广泛使用的库。

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

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

jackson可以绑定到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,这两种方式都没有开销。