如何有效地将 org.json.JSONObject 映射到 POJO? [英] How to efficiently map a org.json.JSONObject to a 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
) - 那么从一种表示到另一种表示的转换将使您免于解析-序列化-解析过程.因此,不是使用接受 String
的 readValue
方法,而是使用 这个版本接受一个 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
可以表示一些额外的类型(例如 BigInteger
、Decimal
等),但它们不是必需的,因为上面的代码涵盖了 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屋!