En Java, necesito consumir JSON (ejemplo a continuación), con una serie de claves arbitrarias, y producir Map<String, String>
. Me gustaría utilizar una biblioteca JSON estándar, compatible a largo plazo para el análisis. Sin embargo, mi investigación muestra que estas bibliotecas están configuradas para la deserialización de las clases Java, donde conoce los campos de antemano. Solo necesito construir Maps.
En realidad, es un paso más complicado que eso, porque las claves arbitrarias no son el nivel superior de JSON; solo ocurren como un sub-objeto para prefs
. El resto es conocido y puede caber en una clase predefinida.
{
"al" : { "type": "admin", "prefs" : { "arbitrary_key_a":"arbitary_value_a", "arbitrary_key_b":"arbitary_value_b"}},
"bert" : {"type": "user", "prefs" : { "arbitrary_key_x":"arbitary_value_x", "arbitrary_key_y":"arbitary_value_y"}},
...
}
En Java, quiero poder tomar esa cadena y hacer algo como:
people.get("al").get("prefs"); // Returns Map<String, String>
¿Cómo puedo hacer esto? Me gustaría usar un analizador estándar bien soportado, evitar excepciones y mantener las cosas simples.
Actualizar
@kumensa ha señalado que esto es más difícil de lo que parece. Ser capaz de hacer:
people.get("al").getPrefs(); // Returns Map<String, String>
people.get("al").getType(); // Returns String
Es igual de buena
Eso debería analizar el JSON a algo como:
public class Person {
public String type;
public HashMap<String, String> prefs;
}
// JSON parsed to:
HashMap<String, Person>
3 respuestas
Con su clase Person
y usando Gson, simplemente puede hacer:
final Map<String, Person> result = new Gson().fromJson(json, new TypeToken<Map<String, Person>>() {}.getType());
Luego, la recuperación de prefs
se logra con people.get("al").getPrefs();
.
Pero tenga cuidado: su cadena json no es válida. No debería comenzar con "people:"
.
public static <T> Map<String, T> readMap(String json) {
if (StringUtils.isEmpty(json))
return Collections.emptyMap();
ObjectReader reader = new ObjectMapper().readerFor(Map.class);
MappingIterator<Map<String, T>> it = reader.readValues(json);
if (it.hasNextValue()) {
Map<String, T> res = it.next();
return res.isEmpty() ? Collections.emptyMap() : res;
}
return Collections.emptyMap();
}
Todo lo que necesita hacer a continuación es comprobar el tipo de Object
. Si es Map
, entonces tienes un objeto. De lo contrario, este es un valor simple.
Puede usar Jackson lib para lograr esto. Ponga lo siguiente en pom.xml.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
Consulte el siguiente fragmento que demuestra lo mismo.
ObjectMapper mapper = new ObjectMapper();
HashMap<String, Object> people = mapper.readValue(jsonString, new TypeReference<HashMap>(){});
Ahora, se deserializa como un Mapa;
Ejemplo completo:
import java.io.IOException;
import java.util.HashMap;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class testMain {
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
String json = "{\"address\":\"3, 43, Cashier Layout, Tavarekere Main Road, 1st Stage, BTM Layout, Ambika Medical, 560029\",\"addressparts\":{\"apartment\":\"Cashier Layout\",\"area\":\"BTM Layout\",\"floor\":\"3\",\"house\":\"43\",\"landmark\":\"Ambika Medical\",\"pincode\":\"560029\",\"street\":\"Tavarekere Main Road\",\"subarea\":\"1st Stage\"}}";
ObjectMapper mapper = new ObjectMapper();
HashMap<String, Object> people = mapper.readValue(json, new TypeReference<HashMap>(){});
System.out.println(((HashMap<String, String>)people.get("addressparts")).get("apartment"));
}
}
Salida: diseño del cajero
Preguntas relacionadas
Nuevas preguntas
java
Java es un lenguaje de programación de alto nivel. Utilice esta etiqueta cuando tenga problemas para usar o comprender el idioma en sí. Esta etiqueta rara vez se usa sola y se usa con mayor frecuencia junto con [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] y [maven].