使用JSON.Simple处理嵌套对象和数组

7
我决定在我的应用程序中使用JSON.Simple来解析Java,而不是GSON或Jackson,因为它们似乎对我的需求过于复杂,并且似乎需要额外的类文件才能按预期工作。我有以下JSON:
{
    "request":{
        "act":"rec_load_all",
        "email":"Redacted",
        "tkn":"Redacted",
        "a":"rec_load_all",
        "z":"Redacted"
    },
    "response":{
        "recs":{
            "has_more":false,
            "count":9,
            "objs":[{
                "rec_id":"1385442465",
                "rec_hash":"1825780e334bcd831034bd9ca62",
                "zone_name":"Redacted",
                "name":"Redacted",
                "display_name":"Redacted",
                "type":"A",
                "prio":null,
                "content":"Redacted",
                "display_content":"Redacted",
                "ttl":"1",
                "ttl_ceil":86400,
                "ssl_id":null,
                "ssl_status":null,
                "ssl_expires_on":null,
                "auto_ttl":1,
                "service_mode":"1",
                "props":{
                    "proxiable":1,
                    "cloud_on":1,
                    "cf_open":0,
                    "ssl":0,
                    "expired_ssl":0,
                    "expiring_ssl":0,
                    "pending_ssl":0,
                    "vanity_lock":0
                }
            }]
        }
    },
    "result":"success",
    "msg":null
}

objs数组列出了9个不同的项目,但出于简单起见,我仅包含了一个。我需要获取has_morecountobjs内的id。我尝试过:

JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(responseString);
JSONArray objs = (JSONArray) jsonObject.get("objs");
Iterator<JSONObject> iterator = objs.iterator();
while (iterator.hasNext()) {
    JSONObject idObj = (JSONObject) iterator.next();
    String id = (String) idObj.get("rec_id");
    System.out.println(id);
}

但是它会出现一个java.lang.NullPointerException错误,所以我假设是因为它嵌套在response -> recs -> objs下没有得到值。我也遵循了几年前的教程,所以可能有些改变了。如果你能解释一下问题并且提供一个修复的例子,我将非常感激,我通过看到学习。
编辑:完整的错误信息。
Exception in thread "main" java.lang.NullPointerException
    at ddns.Net.getId(Net.java:46)
    at ddns.DDNS.main(DDNS.java:7)
Java Result: 1

ddns.Net.getId(Net.java:46) | 迭代器<JSONObject> iterator = objs.iterator(); ddns.DDNS.main(DDNS.java:7) | 仅调用该方法


你能提供堆栈跟踪吗? - Ganesh Chithambalam A.S.
@GaneshChithambalamA.S. 已添加到原帖。 - Novicode
如果它抛出了NPE,那么这意味着idObj对象可能为null。 get抛出NPE是很奇怪的。 它可能返回null,但我不希望它抛出NPE。 - Engineer2021
我在JSON中没有看到id。你是想获取rec_id吗? - evanwong
从您发布的JSON中,"objs"数组中的第一个对象似乎没有"id"属性。 - Ganesh Chithambalam A.S.
@GaneshChithambalamA.S。糟糕,犯了一个简单的错误。问题仍未解决,仍然出现相同的错误。我更新了OP,将“id”更改为“rec_id”。 - Novicode
2个回答

7

你必须从父级中获取任何JSON对象,以下是代码(我已经尝试过并且可以工作):

    public static void main(String[] args) throws IOException, ParseException {

    JSONParser jsonParser = new JSONParser();

    InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("json.json");
    InputStreamReader reader = new InputStreamReader(is);
    JSONObject result = (JSONObject) jsonParser.parse(reader);
    JSONObject response = (JSONObject) result.get("response");
    JSONObject recs = (JSONObject) response.get("recs");

    boolean hasMore = (Boolean) recs.get("has_more");
    JSONArray objs = (JSONArray) recs.get("objs");
    System.out.println(recs);
    System.out.println("has more " + hasMore);

    Iterator objIter = objs.iterator();
    int i = 0;
    while (objIter.hasNext()) {
        i++;
        System.out.println(String.format("obj %d: %s", i, objIter.next()));
    }

}

还有一种对我来说更容易的方式是创建一个具有相同结构的Java Bean,因此...您将解析整个对象,如果您对此方法感兴趣,请告诉我。


为了学习目的,如果您能提供两种方法,那就太好了。 - Novicode
我在你的代码中遇到了问题。Exception in thread "main" java.lang.NullPointerException at java.io.Reader.<init>(Reader.java:78) at java.io.InputStreamReader.<init>(InputStreamReader.java:72) at ddns.Net.getId(Net.java:46) at ddns.DDNS.main(DDNS.java:7) Java Result: 1 - Novicode
我的示例从名为json.json的本地文件读取,为了测试,请使用您自己的解析器而不是我的。所以...从代码行JSONObject result = (JSONObject) jsonParser.parse(reader);中复制我的代码,但是在(reader)的位置上替换为(inputString)。 - Carlos Verdes
要解析一个对象,你可以使用Jackson,这样就不用手动解析了。 - Carlos Verdes
哇,真对不起。我完全忽略了前几行,认为它们是一样的。现在看起来它正在运行。我看了一下Jackson,但它似乎太复杂了。如果你想用那个提供一个例子,那就去吧。不过我并不希望你替我编写程序。 - Novicode
我在String MVC中使用了Jackson,非常容易和不错。请查看这个教程,它非常好,我认为它符合您的需求:http://spring.io/guides/tutorials/rest/ - Carlos Verdes

0

@Carlos Verdes 指引了我正确的方向。

从较大的 JSON 中,我想将联赛名称 My_League 放入字符串中,因为每个用户的名称都不同。

JSON 片段已缩短以保持简洁。

{..."name":"Some_Dude", ... ,"expLevel":221,"league":{"id":12345,"name":"My_League","iconUrls":...},...}

JSON 中存在多个键 "name" 的出现,如果您再次查找键 "name",JSON.Simple 只会检索第一个出现的 "name",即位于开头的 "Some_Dude"

因此,为了解决这个问题,我将 JSON 的该部分,即键 "league",设置为一个 JSON 对象,然后从对象中提取键 "name",以获取我的字符串 "My_League"

JSONObject leagueObj = (JSONObject) each.get("league");
String league = (String)leagueObj.get("name");

重点是,当您提取"league":时,您将获得冒号:之后的所有内容,包括{..}之间的所有内容,直到下一个在闭合大括号}之外的逗号,。在我的情况下,这比您需要的要多,因此您需要解析较小的部分,因此使用JSON对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接