如何检索特定的JsonObject,无论它在Json中的深度如何?

时间:2015-09-08 13:58:00

标签: java json

在自动化测试运行期间,我遇到JsonObject,如跟随,让我们称之为jsonObject

{
    "434": {
        "Test1": {
            "id": "0001",
            "Name": "John"
        }
    },
    "435": {
        "Test2": {
            "id": "0002",
            "Name": "John"
        }
    }
}

我想检索Test1Test2的JsonObject。我可以检索它:

jsonObject.getJsonObject("434").getJsonObject("Test1");
jsonObject.getJsonObject("435").getJsonObject("Test2");

但值434435不是常量。当我重新进行测试时,这次可能是一些不同的数字。因此,我不知道下次会有什么,而不是434435

有什么办法,我可以得到Test1Test2的JsonObject而不管434435(类似jsonObject.someMethod("Test1");)?

我正在使用javax.json库。

2 个答案:

答案 0 :(得分:0)

您可以使用jsonObject.keys()获取当前JSON对象中所有属性名称的迭代器。这将允许您执行以下操作:

Iterable<String> keys = () -> jsonObject.keys();
List<JSONObject> nestedFilteredObjects = stream(keys.spliterator(), false)
        .filter(key -> jsonObject.getJSONObject(key).has("Test"))
        .map(key -> jsonObject.getJSONObject(key))
        .collect(toList());

当然你还需要为json异常添加try-catches,并考虑当属性不是json对象时会发生什么(getJSONObject会抛出异常)。

类似下面的代码应该这样做。请记住,我没有对它进行测试,你可以根据自己的需要进行调整 - 我不知道你的测试中可能有哪些jsons:

private static List<JSONObject> getNestedTestObjects(JSONObject jsonObject) {
    @SuppressWarnings("Convert2MethodRef")
    Iterable<String> keys = () -> jsonObject.keys();
    return stream(keys.spliterator(), false)

            .map(key -> object(jsonObject, key))
            .filter(object -> object instanceof JSONObject)
            .map(object -> (JSONObject) object)

            .filter(object -> object.has("Test"))

            .map(object -> object(object, "Test"))
            .filter(object -> object instanceof JSONObject)
            .map(object -> (JSONObject) object)

            .collect(toList());
}

private static Object object(JSONObject jsonObject, String key) {
    try {
        return jsonObject.get(key);
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
}

答案 1 :(得分:0)

您可以通过传入要搜索的密钥来检索目标对象。该方法将处理向下到每个子对象以找到匹配的键。它将返回第一场比赛。

此外,您可以使用递归例程检索所需深度的所有嵌套JSON对象,如下所示。您选择级别,方法会将每个JsonObject添加到结果列表中。列表最后打印出来。

import java.io.*;
import java.util.*;
import javax.json.*;
import javax.json.stream.JsonGenerator;

public class JsonSearchUtilities {
    public static void main(String[] args) {
        JsonObject jsonObj = readJson("data.json");

        // Search for a JSON object by its key.
        System.out.println("===================\nSearch by Key\n===================");
        searchByKey(jsonObj, "Test2");

        // Search for a JSON objects by depth.
        System.out.println("\n===================\nSearch by Depth\n===================\n");
        searchFullDepth(jsonObj);
    }

    // ========================================================================
    // Main Routines
    // ========================================================================
    public static void searchByKey(JsonObject jsonObj, String key) {
        JsonObject json = getJsonByKey(jsonObj, key);
        String jsonStr = prettyPrint(json);

        System.out.println(jsonStr);
    }

    public static void searchFullDepth(JsonObject jsonObj) {
        JsonArray jsonArr = null;
        int depth = 0;

        do {
            jsonArr = getNestedObjects(jsonObj, depth);
            String jsonStr = prettyPrint(jsonArr);
            System.out.printf("Depth = %d%n%s%s%n%n", depth, "---------", jsonStr);
            depth++;
        } while (jsonArr != null && !jsonArr.isEmpty());
    }

    // ========================================================================
    // Key Search - Search by key
    // ========================================================================
    public static JsonObject getJsonByKey(JsonObject jsonObj, String search) {
        return getJsonByKey(jsonObj, search, 10);
    }

    public static JsonObject getJsonByKey(JsonObject jsonObj, String search, int maxDepth) {
        return getJsonByKey(jsonObj, search, maxDepth, 0);
    }

    /** @private Inner recursive call. */
    private static JsonObject getJsonByKey(JsonObject jsonObj, String search, int maxDepth, int level) {
        if (level < maxDepth && jsonObj != null) {
            Object child = null;

            for (String key : jsonObj.keySet()) {
                child = jsonObj.get(key);

                if (child instanceof JsonObject) {
                    if (key.equals(search)) {
                        return (JsonObject) child;
                    }
                }
            }

            return getJsonByKey((JsonObject) child, search, maxDepth, level + 1);
        }

        return null;
    }

    // ========================================================================
    // Depth Search - Search by depth
    // ========================================================================
    public static JsonArray getNestedObjects(JsonObject jsonObj, int depth) {
        JsonArrayBuilder builder = Json.createArrayBuilder();

        getNestedObjects(jsonObj, builder, depth);

        return builder.build();
    }

    /** @private Inner recursive call. */
    private static void getNestedObjects(JsonObject jsonObj, JsonArrayBuilder builder, int level) {
        if (level == 0) {
            builder.add(jsonObj);
        }

        if (jsonObj != null) {
            for (String key : jsonObj.keySet()) {
                Object child = jsonObj.get(key);

                if (child instanceof JsonObject) {
                    getNestedObjects((JsonObject) child, builder, level - 1);
                }
            }
        }
    }

    // ========================================================================
    // Utilities - Read and write
    // ========================================================================
    private static InputStream getInputStream(String filename, boolean isResource) throws FileNotFoundException {
        if (isResource) {
            ClassLoader loader = JsonSearchUtilities.class.getClassLoader();
            return loader.getResourceAsStream(filename);
        } else {
            return new FileInputStream(new File(filename));
        }
    }

    public static JsonObject readJson(String filename) {
        InputStream stream = null;

        try {
            stream = getInputStream(filename, true);
            JsonReader reader = Json.createReader(stream);
            return reader.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    public static String prettyPrint(JsonStructure json) {
        return jsonFormat(json, JsonGenerator.PRETTY_PRINTING);
    }

    public static String jsonFormat(JsonStructure json, String... options) {
        StringWriter stringWriter = new StringWriter();
        Map<String, Boolean> config = new HashMap<String, Boolean>();

        if (options != null) {
            for (String option : options) {
                config.put(option, true);
            }
        }

        JsonWriterFactory writerFactory = Json.createWriterFactory(config);
        JsonWriter jsonWriter = writerFactory.createWriter(stringWriter);

        jsonWriter.write(json);
        jsonWriter.close();

        return stringWriter.toString();
    }
}

输出

===================
Search by Key
===================

{
    "id":"0002",
    "Name":"John"
}

===================
Search by Depth
===================

Depth = 0
---------
[
    {
        "434":{
            "Test1":{
                "id":"0001",
                "Name":"John"
            }
        },
        "435":{
            "Test2":{
                "id":"0002",
                "Name":"John"
            }
        }
    }
]

Depth = 1
---------
[
    {
        "Test1":{
            "id":"0001",
            "Name":"John"
        }
    },
    {
        "Test2":{
            "id":"0002",
            "Name":"John"
        }
    }
]

Depth = 2
---------
[
    {
        "id":"0001",
        "Name":"John"
    },
    {
        "id":"0002",
        "Name":"John"
    }
]

Depth = 3
---------
[
]