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

时间:2013-11-04 00:55:33

标签: java json parsing jackson

我正在尝试解析Java中的JSON字符串并找到键值对,以便我可以确定JSON对象的近似结构,因为JSON字符串的对象结构是未知的。

例如,一次执行可能有一个像这样的JSON字符串:

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

另一个像这样:

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

如何循环浏览各种JSON元素并确定键及其值?我查看了jackson-core的{​​{3}}。我看到我如何抓住下一个“令牌”并确定它是什么类型的令牌(即字段名称,值,数组启动等),但是,我不知道如何获取实际令牌的值。

例如:

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

jackson或其他库(gsonsimple-json)中是否有类生成树,或者允许循环遍历json元素并获取实际的键名称除了值?

7 个答案:

答案 0 :(得分:67)

看看Jacksons built-in tree model feature

您的代码将是:

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

答案 1 :(得分:15)

如果您可以使用其他图书馆,可以尝试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...
}

答案 2 :(得分:6)

使用Gson库为Unknown Json Object解析找到以下代码。

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

答案 3 :(得分:2)

JSON未知格式HashMap

撰写JSON并阅读Json

{{1}}

答案 4 :(得分:0)

你会对杰克逊的Map感到满意吗?

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

或者可能是JsonNode

JsonNode jsonNode = objectMapper.readTree(String jsonString) 

答案 5 :(得分:0)

要快速将JSON转换为可以“钻取”并使用的Java对象(地图),可以使用json-io(https://github.com/jdereg/json-io)。该库将允许您读入JSON字符串,并返回“地图地图”表示。

如果在JVM中有相应的Java类,则可以读取JSON,并将其直接解析为Java类的实例。

JsonReader.jsonToMaps(String json)

其中json是包含要读取的JSON的String。返回值是一个Map,其中键将包含JSON字段,值将包含关联的值。

JsonReader.jsonToJava(String json) 

将读取相同的JSON字符串,返回值将是序列化为JSON的Java实例。如果您的JVM中的类由

编写,请使用此API
JsonWriter.objectToJson(MyClass foo).

答案 6 :(得分:0)

这是我写的一个示例,展示了如何解析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;
    }
}