Convertir JSON a Mapa

191

¿Cuál es la mejor manera de convertir un código JSON como este:

{ 
    "data" : 
    { 
        "field1" : "value1", 
        "field2" : "value2"
    }
}

en un mapa de Java en el que las claves son (campo1, campo2) y los valores para esos campos son (valor1, valor2).

¿Algunas ideas? ¿Debo usar Json-lib para eso? ¿O mejor si escribo mi propio analizador?

David Santamaria
fuente
He escrito código para esto sin usar ninguna biblioteca. stackoverflow.com/questions/21720759/jsonobject-to-map/…
Vikas Gupta

Respuestas:

336

Espero que estuvieras bromeando sobre escribir tu propio analizador. :-)

Para un mapeo tan simple, la mayoría de las herramientas de http://json.org (sección java) funcionarían. Para uno de ellos (Jackson https://github.com/FasterXML/jackson-databind/#5-minute-tutorial-streaming-parser-generator ), haría:

Map<String,Object> result =
        new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);

(donde JSON_SOURCE es un archivo, secuencia de entrada, lector o cadena de contenido json)

StaxMan
fuente
37
Además, si desea un Mapa escrito (explotando genéricos de Java), puede hacer: Map <String, MyPojo> typedMap = mapper.readValue (jsonStream, new TypeReference <Map <String, MyPojo >> () {});
obe6
55
Si trabaja con el proyecto Maven, necesitará <dependency> <groupId> com.fasterxml.jackson.core </groupId> <artifactId> jackson-databind </artifactId> <version> 2.4.4 </version> </ dependency >
LoBo
2
Y parece que Jackson se mudó desde el 09, así: Jackson data-bind
jacob.mccrumb
@ obe6 Supongo que el OP no está bromeando. ¿Puedes encontrar un solo "JSON" en cualquier parte de tu fragmento de código que no sea ese nombre de variable arbitrario? También estoy luchando por los nombres en Jackson API.
Aetherus
FWTW, mientras que la respuesta de @ obe6 es técnicamente correcto, puede utilizar la forma más corta demasiado: Map<String,Object> result = mapper.readValue(source, Map.class).
StaxMan
36

Usando la biblioteca GSON:

import com.google.gson.Gson;
import com.google.common.reflect.TypeToken;
import java.lang.reclect.Type;

Utiliza el siguiente código:

Type mapType = new TypeToken<Map<String, Map>>(){}.getType();  
Map<String, String[]> son = new Gson().fromJson(easyString, mapType);
David L
fuente
77
Java en su mejor momento: TypeToken<Map<String, Map>>:-)
froderik
2
Con el nuevo TypeToken <Map <String, Object >> funcionará también cuando haya arrays dentro.
9ilsdx 9rvj 0lo
33

Me gusta la biblioteca de google gson .
Cuando no conoces la estructura de json. Puedes usar

JsonElement root = new JsonParser().parse(jsonString);

y luego puedes trabajar con json. por ejemplo, cómo obtener "valor1" de su gson:

String value1 = root.getAsJsonObject().get("data").getAsJsonObject().get("field1").getAsString();
loco_
fuente
19
Esto puede arrojar NullPointerExceptions 5 formas diferentes si obtiene datos inesperados.
dfraser
Puede usar .path () ahora y no arrojará un NPE
C2H50H
18

Utilice JSON lib Ej. Http://www.json.org/java/

// Assume you have a Map<String, String> in JSONObject jdata
@SuppressWarnings("unchecked")
Iterator<String> nameItr = jdata.keys();
Map<String, String> outMap = new HashMap<String, String>();
while(nameItr.hasNext()) {
    String name = nameItr.next();
    outMap.put(name, jdata.getString(name));

}
jd
fuente
12

Mi publicación podría ser útil para otros, así que imagina que tienes un mapa con un objeto específico en valores, algo así:

{  
   "shopping_list":{  
      "996386":{  
         "id":996386,
         "label":"My 1st shopping list",
         "current":true,
         "nb_reference":6
      },
      "888540":{  
         "id":888540,
         "label":"My 2nd shopping list",
         "current":false,
         "nb_reference":2
      }
   }
}

Para analizar este archivo JSON con la biblioteca GSON, es fácil: si su proyecto está mavenizado

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.3.1</version>
</dependency>

Luego usa este fragmento:

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

//Read the JSON file
JsonElement root = new JsonParser().parse(new FileReader("/path/to/the/json/file/in/your/file/system.json"));

//Get the content of the first map
JsonObject object = root.getAsJsonObject().get("shopping_list").getAsJsonObject();

//Iterate over this map
Gson gson = new Gson();
for (Entry<String, JsonElement> entry : object.entrySet()) {
    ShoppingList shoppingList = gson.fromJson(entry.getValue(), ShoppingList.class);
    System.out.println(shoppingList.getLabel());
}

El POJO correspondiente debería ser algo así:

public class ShoppingList {

    int id;

    String label;

    boolean current;

    int nb_reference;

    //Setters & Getters !!!!!
}

Espero eso ayude !

Jad B.
fuente
5

De esta manera funciona como un mapa ...

JSONObject fieldsJson = new JSONObject(json);
String value = fieldsJson.getString(key);

<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.1</version>
</dependency>
Fabio Araujo
fuente
1
Sí, pero debe envolver cada 'get' en try / catch debido a las excepciones JSON.
Maciej Swic
1
podrías escribir una clase JsonMap implements Map<String,Objectpara envolver JSONObject. entonces obtienes la verdadera Mapinterfaz.
Jeffrey Blattman
Por favor agregue las bibliotecas usadas.
mvermand
5

Lo hago de esta manera. Es sencillo.

import java.util.Map;
import org.json.JSONObject;
import com.google.gson.Gson;

public class Main {
    public static void main(String[] args) {
        JSONObject jsonObj = new JSONObject("{ \"f1\":\"v1\"}");
        @SuppressWarnings("unchecked")
        Map<String, String> map = new Gson().fromJson(jsonObj.toString(),Map.class);
        System.out.println(map);
    }
}
Pavana
fuente
Intenté este enfoque pero no funciona ... ¿puedes responder por esto? stackoverflow.com/questions/60329223/…
Siva
3
java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Gson gson = new Gson();
Map<String, Object> categoryicons = gson.fromJson(json, mapType );
nuevoMaziar
fuente
3

La biblioteca JsonTools es muy completa. Se puede encontrar en Github .

Bruno Ranschaert
fuente
2

Con Google Gson 2.7 (probablemente también versiones anteriores, pero probé 2.7) es tan simple como:

Map map = gson.fromJson(json, Map.class);

Que devuelve un Mapa de tipo class com.google.gson.internal.LinkedTreeMapy funciona de forma recursiva en objetos anidados.

isapir
fuente
1

Una alternativa más es json-simple que se puede encontrar en Maven Central :

(JSONObject)JSONValue.parse(someString); //JSONObject is actually a Map.

El artefacto es de 24kbytes, no tiene otras dependencias de tiempo de ejecución.

pcjuzer
fuente
Recibo nullde vuelta desde una simple cadena JSON donde uno de los valores es una matriz de cadenas.
isapir
1

Si está utilizando org.json, JSONObject tiene un método toMap(). Puedes hacer fácilmente:

Map<String, Object> myMap = myJsonObject.toMap();
Omri Levi
fuente
0
import net.sf.json.JSONObject

JSONObject.fromObject(yourJsonString).toMap
Li Rao
fuente
0

Underscore-java biblioteca puede convertir la cadena json en un mapa hash. Soy el mantenedor del proyecto.

Ejemplo de código:

import com.github.underscore.lodash.U;
import java.util.*;

public class Main {

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        String json = "{"
            + "    \"data\" :"
            + "    {"
            + "        \"field1\" : \"value1\","
            + "        \"field2\" : \"value2\""
            + "    }"
            + "}";

       Map<String, Object> data = (Map) U.get((Map<String, Object>) U.fromJson(json), "data");
       System.out.println(data);

       // {field1=value1, field2=value2}
    }
}
Valentyn Kolesnikov
fuente
0

Si necesita Java puro sin dependencias, puede usar la compilación en la API de Nashorn desde Java 8. Está en desuso en Java 11.

Esto es trabajo para mí:

...
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
...

public class JsonUtils {

    public static Map parseJSON(String json) throws ScriptException {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("javascript");

        String script = "Java.asJSONCompatible(" + json + ")";

        Object result = engine.eval(script);

        return (Map) result;
    }
}

Uso de la muestra

JSON

{
    "data":[
        {"id":1,"username":"bruce"},
        {"id":2,"username":"clark"},
        {"id":3,"username":"diana"}
    ]
}

Código:

...
import jdk.nashorn.internal.runtime.JSONListAdapter;
...

public static List<String> getUsernamesFromJson(Map json) {
    List<String> result = new LinkedList<>();

    JSONListAdapter data = (JSONListAdapter) json.get("data");

    for(Object obj : data) {
        Map map = (Map) obj;
        result.add((String) map.get("username"));
    }

    return result;
}
somomas
fuente
0

Prueba este código:

  public static Map<String, Object> convertJsonIntoMap(String jsonFile) {
        Map<String, Object> map = new HashMap<>();
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
            mapper.readValue(jsonFile, new TypeReference<Map<String, Object>>() {
            });
            map = mapper.readValue(jsonFile, new TypeReference<Map<String, String>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }
Braj Thakur
fuente
-1

JSON to Map siempre será un tipo de datos de cadena / objeto. Tengo GSON lib de google.

funciona muy bien y JDK 1.5 es el requisito mínimo.


fuente
1
¿Cómo usaste GSON?
NinjaCoder