简体   繁体   English

在不知道 JSON 格式的情况下用 Java 解析 JSON

[英]Parsing JSON in Java without knowing JSON format

I am trying to parse JSON strings in Java and find the key-value pairs so that I can determine the approximate structure of the JSON object since object structure of JSON string is unknown.我试图用 Java 解析 JSON 字符串并找到键值对,以便我可以确定 JSON 对象的大致结构,因为 JSON 字符串的对象结构是未知的。

For example, one execution may have a JSON string like this:例如,一个执行可能有一个像这样的 JSON 字符串:

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

And another like this:还有一个像这样:

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

How would I cycle through the various JSON elements and determine the keys and their values?我将如何遍历各种 JSON 元素并确定键及其值? I looked at jackson-core 's JsonParser .我查看了jackson-coreJsonParser I see how I can grab the next "token" and determine what type of token it is (ie, field name, value, array start, etc), but, I don't know how to grab the actual token's value.我看到了如何获取下一个“令牌”并确定它是什么类型的令牌(即字段名称、值、数组开始等),但是,我不知道如何获取实际令牌的值。

For example:例如:

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);
  }
}

Is there a class in jackson or some other library ( gson or simple-json ) that produces a tree, or allows one to cycle through the json elements and obtain the actual key names in addition to the values? jackson或其他库( gsonsimple-json )中是否有生成树的类,或者允许循环遍历 json 元素并获取除值之外的实际键名?

Take a look at Jacksons built-in tree model feature .看看Jacksons 内置的树模型功能

And your code will be:你的代码将是:

public void parse(String json)  {
       JsonFactory factory = new JsonFactory();

       ObjectMapper mapper = new ObjectMapper(factory);
       JsonNode rootNode = mapper.readTree(json);  

       Iterator<Map.Entry<String,JsonNode>> fieldsIterator = rootNode.fields();
       while (fieldsIterator.hasNext()) {

           Map.Entry<String,JsonNode> field = fieldsIterator.next();
           System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
       }
}

If a different library is fine for you, you could try org.json :如果不同的库适合你,你可以试试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...
}

Find the following code for Unknown Json Object parsing using Gson library.使用 Gson 库查找未知 Json 对象解析的以下代码。

public class JsonParsing {
static JsonParser parser = new JsonParser();

public static HashMap<String, Object> createHashMapFromJsonString(String json) {

    JsonObject object = (JsonObject) parser.parse(json);
    Set<Map.Entry<String, JsonElement>> set = object.entrySet();
    Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
    HashMap<String, Object> map = new HashMap<String, Object>();

    while (iterator.hasNext()) {

        Map.Entry<String, JsonElement> 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<HashMap<String, Object>> 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 of unknown format to HashMap未知格式的JSONHashMap

writing JSON And reading JsonJSON和读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 <java.util.Map.Entry<String, com.google.gson.JsonElement>> keys = object.entrySet();
        if ( keys.isEmpty() ) {
            System.out.println( "Empty JSON Object" );
        }else {
            Map<String, Object> 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<String, Object> json_UnKnown_Format( Set <java.util.Map.Entry<String, com.google.gson.JsonElement>> keys ){
    Map<String, Object> jsonMap = new HashMap<String, Object>();
    for (Entry<String, JsonElement> 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<Object> array2List = new ArrayList<Object>();
            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 <java.util.Map.Entry<String, com.google.gson.JsonElement>> 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<String, Integer> sortedTree = new TreeMap<String, Integer>();
        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();
    }

}

Here is a sample I wrote shows how I parse a json and mess every number inside it:这是我写的一个示例,展示了我如何解析 json 并弄乱其中的每个数字:

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<Map.Entry<String, JsonNode>> fieldsIterator = rootNode.fields();
            while (fieldsIterator.hasNext()) {
                Map.Entry<String, JsonNode> 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<String, JsonNode> 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;
    }
}

Would you be satisfied with a Map from Jackson?你对杰克逊的Map满意吗?

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

Or maybe a JsonNode ?或者也许是JsonNode

JsonNode jsonNode = objectMapper.readTree(String jsonString) 

To get JSON quickly into Java objects (Maps) that you can then 'drill' and work with, you can use json-io ( https://github.com/jdereg/json-io ).要将 JSON 快速放入 Java 对象(地图)中,然后您可以“钻取”并使用它,您可以使用 json-io ( https://github.com/jdereg/json-io )。 This library will let you read in a JSON String, and get back a 'Map of Maps' representation.这个库会让你读入一个 JSON 字符串,并返回一个“地图地图”表示。

If you have the corresponding Java classes in your JVM, you can read the JSON in and it will parse it directly into instances of the Java classes.如果您的 JVM 中有相应的 Java 类,您可以读取 JSON 并将其直接解析为 Java 类的实例。

JsonReader.jsonToMaps(String json)

where json is the String containing the JSON to be read.其中 json 是包含要读取的 JSON 的字符串。 The return value is a Map where the keys will contain the JSON fields, and the values will contain the associated values.返回值是一个 Map,其中键将包含 JSON 字段,而值将包含关联的值。

JsonReader.jsonToJava(String json) 

will read the same JSON string in, and the return value will be the Java instance that was serialized into the JSON.将读取相同的 JSON 字符串,返回值将是序列化为 JSON 的 Java 实例。 Use this API if you have the classes in your JVM that were written by如果您的 JVM 中有由以下人员编写的类,请使用此 API

JsonWriter.objectToJson(MyClass foo).

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM