Analizando JSON en Java sin conocer el formato JSON

Estoy tratando de analizar cadenas JSON en Java y encontrar los pares clave-valor para poder determinar la estructura aproximada del objeto JSON ya que la estructura de objetos de la cadena JSON es desconocida.

Por ejemplo, una ejecución puede tener una cadena JSON como esta:

{"id" : 12345, "days" : [ "Monday", "Wednesday" ], "person" : { "firstName" : "David", "lastName" : "Menoyo" } } 

Y otro como este:

  {"url" : "http://someurl.com", "method" : "POST", "isauth" : false } 

¿Cómo voy a recorrer los diversos elementos JSON y determinar las claves y sus valores? Miré JsonParser jackson-core . Veo cómo puedo tomar el siguiente “token” y determinar qué tipo de token es (es decir, nombre de campo, valor, inicio de matriz, etc.), pero no sé cómo obtener el valor del token real.

Por ejemplo:

 public void parse(String json) { try { JsonFactory f = new JsonFactory(); JsonParser parser = f.createParser(json); JsonToken token = parser.nextToken(); while (token != null) { if (token.equals(JsonToken.START_ARRAY)) { logger.debug("Start Array : " + token.toString()); } else if (token.equals(JsonToken.END_ARRAY)) { logger.debug("End Array : " + token.toString()); } else if (token.equals(JsonToken.START_OBJECT)) { logger.debug("Start Object : " + token.toString()); } else if (token.equals(JsonToken.END_OBJECT)) { logger.debug("End Object : " + token.toString()); } else if (token.equals(JsonToken.FIELD_NAME)) { logger.debug("Field Name : " + token.toString()); } else if (token.equals(JsonToken.VALUE_FALSE)) { logger.debug("Value False : " + token.toString()); } else if (token.equals(JsonToken.VALUE_NULL)) { logger.debug("Value Null : " + token.toString()); } else if (token.equals(JsonToken.VALUE_NUMBER_FLOAT)) { logger.debug("Value Number Float : " + token.toString()); } else if (token.equals(JsonToken.VALUE_NUMBER_INT)) { logger.debug("Value Number Int : " + token.toString()); } else if (token.equals(JsonToken.VALUE_STRING)) { logger.debug("Value String : " + token.toString()); } else if (token.equals(JsonToken.VALUE_TRUE)) { logger.debug("Value True : " + token.toString()); } else { logger.debug("Something else : " + token.toString()); } token = parser.nextToken(); } } catch (Exception e) { logger.error("", e); } } 

¿Hay una clase en jackson o en alguna otra biblioteca ( gson o simple-json ) que produzca un árbol o le permita a uno pasar por los elementos json y obtener los nombres de las teclas reales además de los valores?

Eche un vistazo a la función de modelo de árbol incorporada de Jackson .

Y tu código será:

 public void parse(String json) { JsonFactory factory = new JsonFactory(); ObjectMapper mapper = new ObjectMapper(factory); JsonNode rootNode = mapper.readTree(json); Iterator> fieldsIterator = rootNode.fields(); while (fieldsIterator.hasNext()) { Map.Entry field = fieldsIterator.next(); System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue()); } } 

Si una biblioteca diferente está bien para ti, puedes probar org.json :

 JSONObject object = new JSONObject(myJSONString); String[] keys = JSONObject.getNames(object); for (String key : keys) { Object value = object.get(key); // Determine type of value and do something with it... } 

Busque el siguiente código para el análisis de objetos desconocidos Json utilizando la biblioteca Gson.

 public class JsonParsing { static JsonParser parser = new JsonParser(); public static HashMap createHashMapFromJsonString(String json) { JsonObject object = (JsonObject) parser.parse(json); Set> set = object.entrySet(); Iterator> iterator = set.iterator(); HashMap map = new HashMap(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); String key = entry.getKey(); JsonElement value = entry.getValue(); if (null != value) { if (!value.isJsonPrimitive()) { if (value.isJsonObject()) { map.put(key, createHashMapFromJsonString(value.toString())); } else if (value.isJsonArray() && value.toString().contains(":")) { List> list = new ArrayList<>(); JsonArray array = value.getAsJsonArray(); if (null != array) { for (JsonElement element : array) { list.add(createHashMapFromJsonString(element.toString())); } map.put(key, list); } } else if (value.isJsonArray() && !value.toString().contains(":")) { map.put(key, value.getAsJsonArray()); } } else { map.put(key, value.getAsString()); } } } return map; } } 

JSON de formato desconocido para HashMap

escribiendo JSON y leyendo a Json

 public static JsonParser parser = new JsonParser(); public static void main(String args[]) { writeJson("JsonFile.json"); readgson("JsonFile.json"); } public static void readgson(String file) { try { System.out.println( "Reading JSON file from Java program" ); FileReader fileReader = new FileReader( file ); com.google.gson.JsonObject object = (JsonObject) parser.parse( fileReader ); Set > keys = object.entrySet(); if ( keys.isEmpty() ) { System.out.println( "Empty JSON Object" ); }else { Map map = json_UnKnown_Format( keys ); System.out.println("Json 2 Map : "+map); } } catch (IOException ex) { System.out.println("Input File Does not Exists."); } } public static Map json_UnKnown_Format( Set > keys ){ Map jsonMap = new HashMap(); for (Entry entry : keys) { String keyEntry = entry.getKey(); System.out.println(keyEntry + " : "); JsonElement valuesEntry = entry.getValue(); if (valuesEntry.isJsonNull()) { System.out.println(valuesEntry); jsonMap.put(keyEntry, valuesEntry); }else if (valuesEntry.isJsonPrimitive()) { System.out.println("P - "+valuesEntry); jsonMap.put(keyEntry, valuesEntry); }else if (valuesEntry.isJsonArray()) { JsonArray array = valuesEntry.getAsJsonArray(); List array2List = new ArrayList(); for (JsonElement jsonElements : array) { System.out.println("A - "+jsonElements); array2List.add(jsonElements); } jsonMap.put(keyEntry, array2List); }else if (valuesEntry.isJsonObject()) { com.google.gson.JsonObject obj = (JsonObject) parser.parse(valuesEntry.toString()); Set > obj_key = obj.entrySet(); jsonMap.put(keyEntry, json_UnKnown_Format(obj_key)); } } return jsonMap; } @SuppressWarnings("unchecked") public static void writeJson( String file ) { JSONObject json = new JSONObject(); json.put("Key1", "Value"); json.put("Key2", 777); // Converts to "777" json.put("Key3", null); json.put("Key4", false); JSONArray jsonArray = new JSONArray(); jsonArray.put("Array-Value1"); jsonArray.put(10); jsonArray.put("Array-Value2"); json.put("Array : ", jsonArray); // "Array":["Array-Value1", 10,"Array-Value2"] JSONObject jsonObj = new JSONObject(); jsonObj.put("Obj-Key1", 20); jsonObj.put("Obj-Key2", "Value2"); jsonObj.put(4, "Value2"); // Converts to "4" json.put("InnerObject", jsonObj); JSONObject jsonObjArray = new JSONObject(); JSONArray objArray = new JSONArray(); objArray.put("Obj-Array1"); objArray.put(0, "Obj-Array3"); jsonObjArray.put("ObjectArray", objArray); json.put("InnerObjectArray", jsonObjArray); Map sortedTree = new TreeMap(); sortedTree.put("Sorted1", 10); sortedTree.put("Sorted2", 103); sortedTree.put("Sorted3", 14); json.put("TreeMap", sortedTree); try { System.out.println("Writting JSON into file ..."); System.out.println(json); FileWriter jsonFileWriter = new FileWriter(file); jsonFileWriter.write(json.toJSONString()); jsonFileWriter.flush(); jsonFileWriter.close(); System.out.println("Done"); } catch (IOException e) { e.printStackTrace(); } } 

¿Estaría satisfecho con un Map de Jackson?

 ObjectMapper objectMapper = new ObjectMapper(); Map map = objectMapper.readValue(jsonString, new TypeReference>(){}); 

¿O tal vez un JsonNode ?

 JsonNode jsonNode = objectMapper.readTree(String jsonString) 

Para obtener JSON rápidamente en objetos Java (Mapas) que luego puede ‘perforar’ y trabajar, puede usar json-io ( https://github.com/jdereg/json-io ). Esta biblioteca le permitirá leer en una cadena JSON y obtener una representación de ‘Mapa de mapas’.

Si tiene las clases de Java correspondientes en su JVM, puede leer el JSON y lo analizará directamente en instancias de las clases de Java.

 JsonReader.jsonToMaps(String json) 

donde json es la cadena que contiene el JSON para leer. El valor de retorno es un Mapa donde las claves contendrán los campos JSON, y los valores contendrán los valores asociados.

 JsonReader.jsonToJava(String json) 

leerá la misma cadena JSON, y el valor de retorno será la instancia de Java que se serializó en el JSON. Use esta API si tiene las clases en su JVM que fueron escritas por

 JsonWriter.objectToJson(MyClass foo). 

Aquí hay una muestra que escribí muestra cómo analizo un json y meto todos los números dentro de él:

 public class JsonParser { public static Object parseAndMess(Object object) throws IOException { String json = JsonUtil.toJson(object); JsonNode jsonNode = parseAndMess(json); if(null != jsonNode) return JsonUtil.toObject(jsonNode, object.getClass()); return null; } public static JsonNode parseAndMess(String json) throws IOException { JsonNode rootNode = parse(json); return mess(rootNode, new Random()); } private static JsonNode parse(String json) throws IOException { JsonFactory factory = new JsonFactory(); ObjectMapper mapper = new ObjectMapper(factory); JsonNode rootNode = mapper.readTree(json); return rootNode; } private static JsonNode mess(JsonNode rootNode, Random rand) throws IOException { if (rootNode instanceof ObjectNode) { Iterator> fieldsIterator = rootNode.fields(); while (fieldsIterator.hasNext()) { Map.Entry field = fieldsIterator.next(); replaceObjectNode((ObjectNode) rootNode, field, rand); } } else if (rootNode instanceof ArrayNode) { ArrayNode arrayNode = ((ArrayNode) rootNode); replaceArrayNode(arrayNode, rand); } return rootNode; } private static void replaceObjectNode(ObjectNode rootNode, Map.Entry field, Random rand) throws IOException { JsonNode childNode = field.getValue(); if (childNode instanceof IntNode) { (rootNode).put(field.getKey(), rand.nextInt(1000)); } else if (childNode instanceof LongNode) { (rootNode).put(field.getKey(), rand.nextInt(1000000)); } else if (childNode instanceof FloatNode) { (rootNode).put(field.getKey(), format(rand.nextFloat())); } else if (childNode instanceof DoubleNode) { (rootNode).put(field.getKey(), format(rand.nextFloat())); } else { mess(childNode, rand); } } private static void replaceArrayNode(ArrayNode arrayNode, Random rand) throws IOException { int arrayLength = arrayNode.size(); if(arrayLength == 0) return; if (arrayNode.get(0) instanceof IntNode) { for (int i = 0; i < arrayLength; i++) { arrayNode.set(i, new IntNode(rand.nextInt(10000))); } } else if (arrayNode.get(0) instanceof LongNode) { arrayNode.removeAll(); for (int i = 0; i < arrayLength; i++) { arrayNode.add(rand.nextInt(1000000)); } } else if (arrayNode.get(0) instanceof FloatNode) { arrayNode.removeAll(); for (int i = 0; i < arrayLength; i++) { arrayNode.add(format(rand.nextFloat())); } } else if (arrayNode.get(0) instanceof DoubleNode) { arrayNode.removeAll(); for (int i = 0; i < arrayLength; i++) { arrayNode.add(format(rand.nextFloat())); } } else { for (int i = 0; i < arrayLength; i++) { mess(arrayNode.get(i), rand); } } } public static void print(JsonNode rootNode) throws IOException { System.out.println(rootNode.toString()); } private static double format(float a) { return Math.round(a * 10000.0) / 100.0; } }