convert - json to string java
¿Cómo asignar de manera eficiente un org.json.JSONObject a un POJO? (3)
Añadiendo una respuesta a una vieja pregunta, pero ...
Jackson puede enlazar a / desde los tipos org.json. En general, puede convertir entre cualquier tipo al que se puede enlazar, mediante la serialización efectiva (aunque no realmente) a JSON y la deserialización.
Si tiene el JsonOrgModule registrado, simplemente puede hacer la conversión directamente desde 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;
}
Mencioné que esto está efectivamente serializando? Es cierto, serializa el objeto de entrada en un TokenBuffer, que representa una secuencia de eventos de análisis JSON, pero con menos impacto de la creación de cadenas, etc., ya que puede hacer referencia en gran medida a los datos de la entrada. Luego alimenta este flujo a un deserializador para producir el objeto de salida.
Por lo tanto, es algo similar a la sugerencia de convertir JSONObject en un JsonNode, pero es mucho más general. Si es realmente más eficiente o no necesitaría una medición: ya sea que construyas un JsonNode como un intermediario o un TokenBuffer, ninguna de las dos es sin gastos generales.
Esta pregunta debe haber sido hecha antes, pero no pude encontrarla.
Estoy usando una biblioteca de terceros para recuperar datos en formato JSON. La biblioteca me ofrece los datos como org.json.JSONObject
. Quiero asignar este JSONObject
a un POJO (objeto Java antiguo llano) para un código / acceso más sencillo.
Para la asignación, actualmente uso el ObjectMapper
de la biblioteca Jackson de esta manera:
JSONObject jsonObject = //...
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(jsonObject.toString(), MyPojoClass.class);
A mi entender, el código anterior se puede optimizar significativamente, porque actualmente los datos en el JSONObject
, que ya están analizados, se introducen nuevamente en una cadena de deserialización de serialización con el método JSONObject.toString()
y luego al ObjectMapper
.
Quiero evitar estas dos conversiones ( toString()
y análisis). ¿Hay alguna forma de usar JSONObject
para asignar sus datos directamente a un POJO?
Si no estás vinculado con Jackson, puedes usar la práctica biblioteca de google-gson como alternativa. Requiere solo un tarro y es muy simple de usar:
Convertir un objeto java en una cadena JSON:
String json_string = new Gson().toJson(an_object);
Creando un objeto java a partir de una cadena JSON:
MyObject obj = new Gson().fromJson(a_json_string, MyObject.class);
No sé sobre el rendimiento en comparación con Jackson, pero es difícil ser más simple que esto ... Gson es una biblioteca estable y ampliamente utilizada.
Ya que tiene una representación abstracta de algunos datos JSON (un objeto org.json.JSONObject
) y planea usar la biblioteca Jackson, que tiene su propia representación abstracta de datos JSON ( com.fasterxml.jackson.databind.JsonNode
) - luego, una conversión de una representación a la otra lo salvaría del proceso de análisis de serialización de análisis. Entonces, en lugar de usar el método readValue
que acepta un String
, JsonParser
esta versión que acepta un JsonParser
:
JSONObject jsonObject = //...
JsonNode jsonNode = convertJsonFormat(jsonObject);
ObjectMapper mapper = new ObjectMapper();
MyPojoClass myPojo = mapper.readValue(new TreeTraversingParser(jsonNode), MyPojoClass.class);
JSON es un formato muy simple, por lo que no debería ser difícil crear el convertJsonFormat
a mano. Aquí está mi intento:
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;
}
Tenga en cuenta que, si bien el JsonNode
de Jackson puede representar algunos tipos adicionales (como BigInteger
, Decimal
, etc.) no son necesarios, ya que el código anterior cubre todo lo que JSONObject
puede representar.