如何安全地使用JSON.parse解析一个字符串对象,该对象可能是一个简单的字符串或一个字符串对象?

6
我需要能够解析一个对象格式或纯字符串格式的字符串。最安全的方法是什么?
我尝试了JSON.parse(data),但在数据为纯字符串的情况下无法工作。

编辑 - 已选择的解决方案

谢谢您,以下是我解决问题的方法:
try {
    dataObj = JSON.parse(data);
} catch (err) {
    if (typeof data === "object") {
        dataObj = data;
    } else {
        dataObj = {};
    }
}

如果 data 可以是一个对象,为什么不在尝试解析之前测试它呢?这样更有意义。另外,如果它可以是一个对象,为什么不在你的问题中提到呢?你说值将是一个字符串。 - Felix Kling
在我写完这个问题后,我发现了更多的边缘情况。 - Ravit
3个回答

3

使用try catch:

var result;
try {
   result = JSON.parse(data);
} catch (err) {
   if (typeof data == 'string') result = data;
   else console.error(err);
}

现在的问题不是如何区分由无效JSON和“纯字符串”引起的错误吗?(第一个是意外的,但第二个是预期的)或者您是否认为如果数据包含JSON,它将始终有效? - Felix Kling
修正后:如果(typeof data == 'string'),则result = data;否则console.error(err); - monkey
嗯,你为什么会期望 data 是除了字符串以外的其他类型呢?你是把 JSON 和 JavaScript 对象搞混了吗? - Felix Kling
同意@FelixKling的观点,检查需要对所有情况都安全。 - Ravit

3
创建一个帮助函数并使用它。
function parseValue(value) {
    try
    {
        return JSON.parse(value);
    }
    catch (ex)
    {
        // JSON format was invalid
        // handle errors is you need to
    }

    return value;
}

如果你足够勇敢,你还可以扩展String.prototype,这样调用它就变得非常简单直接。
String.prototype.parseJSON = String.prototype.parseJSON || function() {
    try
    {
        return JSON.parse(this);
    }
    catch (ex)
    {
        // JSON format was invalid
        // handle errors is you need to
    }

    return this;
};

然后,您只需按以下方式调用它:

// string in a variable
var s = "Some non-JSON string";
s.parseJSON();
// string literal
'{"b":true,"n":1}'.parseJSON();

只是指出这种方法的“问题”(这并不意味着这是一个不好的解决方案!):正如已经说过的,try/catch 处理每个错误,但实际上有两种错误情况我们可能想要区分:1)输入是格式不正确的 JSON。这是一个意外的错误,在这种情况下,JSON 生成应该被修复。2)输入是纯字符串。这是预期的,因此程序应该继续运行。公平地说,如果使用本机函数生成 JSON,则情况 1 相当不太可能。在这种假设下,try/catch 是适当的解决方案。 - Felix Kling

0

假设JSON格式始终相同,您还可以检查字符串是否以{"(或仅为{)开头,然后再使用JSON.parse进行解析。

但这真的取决于可能的输入。


1
这还可以,但最终你会改变代码,而try/catch则可将其全部涵盖...我是什么意思呢?JSON 对象可以以 {[ 开始。但这只是我能想到的一些开头。JSON 字符串可能有其他不同的开头。因此,为了使您的代码更加强大,以涵盖任何字符串,我认为使用try/catch是更好的方法。 - Robert Koritnik
@Robert:这完全取决于上下文和可能的输入。使用try...catch的缺点是会忽略JSON真正出错的情况,那么这样真的更加健壮吗?另外,[表示数组而不是对象。根据他们的说法,如果是JSON格式,我假设它将始终是一个对象。 - Felix Kling
@FelixKling:那么在你的代码中,你会在哪里处理无效的JSON,例如{{ this is worth nothing }}?在这种情况下,try/catch可以工作,而你的if/else认为它是JSON,并在解析时出错。 - Robert Koritnik
@Robert:我希望它抛出一个错误,这样我就知道了。如果你悄悄地捕捉它,很可能你不知道有问题。 - Felix Kling
但在浏览器中抛出的错误不会显示给用户,作为开发者,你必须“处理它们”,并向用户提供可读的错误信息。这实际上意味着什么?那就是你最终会使用 try/catch 代码块。那么,如果你可以用处理错误的 try/catch 来覆盖所有情况,为什么还要使用 if/else 呢? - Robert Koritnik
@Robert:我认为如果JSON格式不正确,那么这就是一个bug,开发人员需要修复生成JSON的任何问题。 - Felix Kling

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