递归地解析JSON对象 - Java

时间:2016-06-16 00:47:25

标签: java json performance parsing recursion

我有一个带有对象列表的JSON,列表中的任何项目都可以具有null或与键值相同的对象。我正在寻找一种更快的方法来解析json以得出我的最终结果。 数据结构看起来像 -

[
    {
        "firstName": "Bruce",
        "familyMembers": null
    },
    {
        "firstName": "Gates Family",
        "familyMembers": [
            {
                "firstName": "Bill",
                "familyMembers": null
            },
            {
                "firstName": "Steve",
                "familyMembers": null
            }
        ]
    },
    {
        "firstName": "Lee",
        "familyMembers": null
    },
    {
        "firstName": "Chan",
        "familyMembers": null
    }
]

输出应该是一个set =(" Bruce"," Bill"," Steve"," Lee",&#34 ;陈"。)

我正在寻找一种在Java中做到这一点的最好方法,这样我就不会因为陷入这个解析地狱而增加我的响应时间。 感谢你的时间。

3 个答案:

答案 0 :(得分:1)

尝试我的递归实现。

public static void jsonArrayToSet(JSONArray jAry, Set<String> result, String targetKey, String subArrayKey, boolean includeNode){
    try {
        for (int i = 0; i < jAry.length(); i++) {
            JSONObject jObj = jAry.getJSONObject(i);
            boolean hasSubArray = false;
            JSONArray subArray = null;
            if(jObj.has(subArrayKey)){
                Object possibleSubArray = jObj.get(subArrayKey);
                if(possibleSubArray instanceof JSONArray){
                    hasSubArray = true;
                    subArray = (JSONArray) possibleSubArray;
                }
            }
            if(hasSubArray){
                if(includeNode){
                    result.add(jObj.getString(targetKey));
                }
                jsonArrayToSet(subArray, result, targetKey, subArrayKey, includeNode);
            } else {
                result.add(jObj.getString(targetKey));
            }
        }
    } catch (JSONException e){
        e.printStackTrace();
    }
}

jAry:来源JSONArray

result:您要写的Set

targetKey:映射到您要添加到result的条目的键。

subArrayKey:映射到子JSONArray的键。

includeNode:当前JSONOnject是包含子数组的节点时,请将其添加到result

在您的情况下,您可以致电:

jsonArrayToSet(yourJsonArray, yourSet, "firstName", "familyMembers", false);

答案 1 :(得分:1)

正如我的评论所述。

您的第一个问题是JSON文件中的内容。根据标准,它应该包含一组{}。

实施例

{ 
    "members": [
        {
            "firstName": "Bruce",
            "familyMembers": null
        },
        {
            "firstName": "Gates Family",
            "familyMembers": [
                {
                    "firstName": "Bill",
                    "familyMembers": null
                },
                {
                    "firstName": "Steve",
                    "familyMembers": null
                }
            ]
        },
        {
            "firstName": "Lee",
            "familyMembers": null
        },
        {
            "firstName": "Chan",
            "familyMembers": null
        }
    ]
}

另外,我认为“盖茨家族”的价值应该是产出的一部分?因为它在“FirstName”属性下。

无论如何,这是我的解决方案,它基于org.json库。它还使用Goggle的GSon库,我用它来读取JSON文件。

import org.json.*;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

public class solution {

    public static final String JSON_DATA_FILE_PATH = "./data/source_37848106.json";

    private static boolean hasMoreFamilyName(JSONObject json) {
        return json.has("familyMembers") && json.get("familyMembers") != JSONObject.NULL;
    }

    private static void trackFirstName(Map<String, Integer> nameTracker, JSONObject json) {
        if (!nameTracker.containsKey(json.getString("firstName"))) {
            nameTracker.put(json.getString("firstName"), /*DUMMY VALUE =*/1);
        }
    }

    private static void getNames(Map<String,Integer> nameTracker, JSONArray jsonArr) {
        for (int i = 0; i< jsonArr.length(); i++) {
            JSONObject item = jsonArr.getJSONObject(i);
            if (hasMoreFamilyName(item)) {
                getNames(nameTracker, item.getJSONArray("familyMembers"));
            }
            trackFirstName(nameTracker, item);
        }
    }

    public static void main(String[] args) {
        Map<String, Integer> nameTracker = new HashMap<>();

        try {
            String text = Files.toString(new File(JSON_DATA_FILE_PATH), Charsets.UTF_8);
            JSONObject json = new JSONObject(text);
            getNames(nameTracker, json.getJSONArray("members"));
        }
        catch (Exception ex) {
            System.out.println("Something is wrong.");
        }

        for (Map.Entry<String,Integer> entry : nameTracker.entrySet()) {
        System.out.println(entry.getKey());
    }
}

答案 2 :(得分:0)

您可以使用jackson-databind-2.6.5.jar

中定义的ObjectMapper

使用类似于json模式的字段定义一个java类,然后将它们绑定为:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;   

 ObjectMapper objectMapper = new ObjectMapper();
 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
 Family family=objectMapper.readValue(jsonString, Family.class);

现在您将拥有一个类似于json字符串模式的java对象,您可以按自己喜欢的方式打印它。