如何解析以数字为键的JSON

14
我有以下的JSON数据,可惜我无法控制这个输出。
{
"questions": {
    "9733": {
        "text": "Star Trek or Star Wars?",
        "answers": {
            "41003": "Star Trek",
            "41004": "Star Wars",
            "41005": "Neither is superior in my opinion; both great in their own ways",
            "41006": "Not a fan",
            "41007": "I don't have an opinion on this"
        }
    },
    "25272": {
        "text": "Which of these summer movies are you looking forward to the most?",
        "answers": {
            "99545": "World War Z",
            "99546": "Monsters University ",
            "99547": "White House Down",
            "99548": "Man of Steel",
            "99549": "Lone Ranger",
            "99550": "The Wolverine"
        }
    },
    "27547": {
        "text": "Should the U.S. attack Syria?",
        "answers": {
            "107453": "Yes",
            "107454": "No"
        }
    }
}
}

我将使用json.parse来解析这个内容。要获取第一个问题的文本,我通常会执行以下操作。
var jsonData = JSON.parse(data);//Where data = the json above
console.log(jsonData.questions.9733.text);//Obviously this fails

然而,显然JavaScript不喜欢那个数字。你如何建议访问第一个问题的文本?我更喜欢将json设置为问题数组。不幸的是,我无法控制此JSON的输出。
另外,当它们出现时,我也不知道键是什么,但这是完全不同的问题。我愿意接受任何关于如何解析这个奇怪的JSON输出的建议。

1
我只会使用 jsonData['questions']['9733']['text'] - NullUserException
1
jsonData.questions[9733].text 应该可以工作。在 JS 中,foo.barfoo['bar'] 是等价的。 - IMSoP
自从我开始学习JavaScript以来,每当遇到一点小问题,我就不得不上Google查找解决方法。这里没有什么是直观的。为什么不能像这样简单: jsonData.questions.9733.text呢?我不知道。 - Atul
@Atul,真是太疯狂了,我在8年前的帖子上收到评论。但原因是JSON永远不应该以你看到的方式进行格式化。这是与JavaScript无关的特定问题,而是与创建上述JSON格式的人非常糟糕的决策有关。该对象应该被格式化为一个数组,而不是一系列随机对象串联在一起。 - Caimen
5个回答

14

你需要使用括号表示法

console.log(jsonData.questions["9733"].text);

但是因为括号内的值将自动转换为字符串,所以这也可以工作:
console.log(jsonData.questions[9733].text);

然而,请注意,使用非字符串作为属性名称通常是不好的做法,并且可能会导致一些微妙的问题,例如,如果属性名称是"001",那么[001]无法正常工作。

属性名称被转换为字符串,因此您的最后一个示例无法正常工作,因为 001 被转换为 "1" 而不是 "001" - NullUserException
1
@NullUserException 不,实际上不会(至少在Opera/Chrome浏览器中不会)。当我将最后一个示例尝试作为数字时,我得到的是“undefined”,但当我将其转换为字符串时,我获得的是实际数据。 - Cypher
@NullUserException 最后一个例子按照描述的方式工作(如果属性名称为“001”,那么[001]将不起作用。),至少在Opera和Chrome中是这样的。 :) - Cypher
@Cypher 是的,应该是这样的。 - NullUserException
谢谢你的帮助,我很感激。也许我会联系API的创建者,建议使用数组而不是数字作为键。这将使我的生活更加轻松。 - Caimen

2

我相信您可以通过与数组相同的语法访问数据:

console.log(jsonData.questions[9733].text);

1
@sabof 我并没有说它是一个数组,而是语法相同。 - Tohveli
1
@NullUserException 承认,有时会失败(请参见p.s.w.g的答案),但在这种特定情况下确实有效。我不明白这怎么能使这个答案“错误”。 - Cypher
3
这里的反对意见在于具体的语言“as in any array”,这可能被解读为表明对象实际上是一个数组。我不认为这是Tohveli的意思,但更清晰的措辞应该是“as in an array”。 - p.s.w.g
1
我取消了踩的操作。但请注意,使用此语法时,数字与字符串有一个警告(var[123] vs var["123"])。请参考@p.s.w.g的回答。 - NullUserException

2

1
如果您必须使用数字作为键... 您可以像这样访问它们:
var text = jsonData.questions["9733"].text;

编辑:您也可以使用数字9733访问它。如果键是非数字的,则必须是字符串,否则只需要是数字。

-1

如果你正在使用Java 8,尝试使用Ason。Gradle依赖项编译'org.arivu:ason:1.0.3'。

Java代码如下:

Ason ason = new Ason();
Object json = ason.fromJson("<<JSON String!>>");
System.out.println(Ason.getJson(json, "questions.9733.text", null)):

1
只是让你知道,你需要查看问题中的标签,以确保你理解使用的是哪种编程语言。在这种情况下,标签是JavaScript而不是Java。 - Caimen

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