错误信息:“Uncaught SyntaxError: Unexpected token with JSON.parse”

254
第三行发生错误的原因是什么?

var products = [{
  "name": "Pizza",
  "price": "10",
  "quantity": "7"
}, {
  "name": "Cerveja",
  "price": "12",
  "quantity": "5"
}, {
  "name": "Hamburguer",
  "price": "10",
  "quantity": "2"
}, {
  "name": "Fraldas",
  "price": "6",
  "quantity": "2"
}];
console.log(products);
var b = JSON.parse(products); //unexpected token o

打开控制台查看错误信息


24
你没有任何 JSON 吗?它是一种数组/对象文字表示法。 - Bergi
顺便提一下:我注意到如果你使用JQuery,并通过data属性获取一个JSON字符串,例如$('#mydata').data('person');,那么JQuery会自动将数据字符串转换为JSON对象。这里不需要使用JSON.parse() - Avatar
附言:我注意到,如果你使用JQuery并通过data属性获取JSON字符串,例如$('#mydata').data('person');,那么JQuery会自动将数据字符串转换为JSON对象。这里不需要使用JSON.parse() - undefined
24个回答

264

products是一个对象。(从对象字面量创建)

JSON.parse()用于将包含 JSON 符号的字符串转换为 JavaScript 对象。

您的代码将该对象转换为字符串(通过调用.toString()),以尝试将其解析为 JSON 文本。
默认的.toString()返回"[object Object]",这不是有效的 JSON; 因此会出现错误。


5
数组是对象;这是.toString()方法返回的内容(根据规范)。 - SLaks
1
先将对象转换成字符串,这是解决方案吗? - Mohammed Noureldin
11
不需要;解决方案是什么都不做,继续使用你的物品。 - SLaks
4
如果我使用Ajax从远程服务获取数据,并且它返回Json响应,我想将该响应保存在JavaScript数组对象中,该怎么办? - Mohammed Noureldin
1
@MohammedNoureldin:如果你有一个对象,你就不需要解析它。如果你有一个字符串,你也不会出现错误。 - SLaks
显示剩余3条评论

165

假设你知道它是有效的JSON,但仍然出现以下情况...

在这种情况下,很可能字符串中存在来自任何来源的隐藏/特殊字符。当您将其粘贴到验证器中时,它们会丢失 - 但是在字符串中它们仍然存在。那些不可见的字符会破坏JSON.parse()

如果s是您的原始JSON,则使用以下方法清理:

// Preserve newlines, etc. - use valid JSON
s = s.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");
// Remove non-printable and other non-valid JSON characters
s = s.replace(/[\u0000-\u0019]+/g,"");
var o = JSON.parse(s);

2
Base64解码后出现了尾随特殊字符,你的方法帮了我很大的忙!谢谢。 - Guillaume
不要相信返回无效JSON的源。只需通知他们数据已损坏,应该修复它。如果您尝试像这样或类似地“恢复”响应,则会保持不稳定的通信。 - Onur Yıldırım
应该使用s = s.replace(/[\u0000-\u001F]+/g,"");来替换所有控制字符,而不是s = s.replace(/[\u0000-\u0019]+/g,"");,对吗? - HongchaoZhang
s.replace(/\\n/g, "\\n") 的逻辑是什么?我测试了一下,例如 "abc\\ndef".replace(/\\n/g,"\\'");,它会将其转换为 abc\'def。你为什么要这样做?JSON不允许以反斜杠结尾的行吗?你能否简单地解释一下你的例子是做什么的以及为什么要这样做? - barlop
谢谢,这真的很有帮助。特别是当您将JSON复制到剪贴板中并且控制台中存在隐藏的特殊换行符时。 - ChiHang
我有有效的JSON {"comment": "fixes\n"},并尝试解析它JSON.parse('{"comment": "fixes\n"}'),但控制台返回 SyntaxError: Unexpected token,即使它是有效的JSON。能否有人解释一下原因? - Pavol Travnik

82

看起来你想要将对象转化为字符串,而不是解析。所以你可以这样做:

JSON.stringify(products);

发生错误的原因是 JSON.parse() 期望一个 String 值,而 products 是一个 Array

注:我认为它尝试着解析 json.parse('[object Array]'),但由于在 [ 后面出现了标记 o,而抱怨错误。


对我来说起作用了。我将所有数组元素和数组本身都转换为字符串,然后json.parse()成功了。 - cansu
但是,你为什么要这样做呢?它已经是一个对象了。为什么要将其字符串化,然后再解析回一个对象呢? - Clonkex
@Clonkex 可以将其写入文件、作为文本发布、打印在文档上、进行字符串搜索、持久化在数据库中、调试、嘲笑它以及其他一些原因... - Onur Yıldırım
我的观点是,你不会将其转换为字符串然后立即解析。那样做没有意义(除非你想进行深度复制或类似的奇怪操作)。也许你是说要用stringify替换parse,但听起来你是在说先stringify以便parse工作(正如我所说,这是没有意义的)。 - Clonkex
我不知道你是如何从答案中得出“首先字符串化”的,但我加上了“不解析”以使其更清晰。 - Onur Yıldırım

36

JSON.parse需要一个字符串作为参数。您需要将JSON对象转换为字符串以解决该问题。

products = [{"name":"Pizza","price":"10","quantity":"7"}, {"name":"Cerveja","price":"12","quantity":"5"}, {"name":"Hamburguer","price":"10","quantity":"2"}, {"name":"Fraldas","price":"6","quantity":"2"}];
console.log(products);
var b = JSON.parse(JSON.stringify(products));  //solves the problem

这与之前的答案有何不同? - Peter Mortensen
这很简单直接,只是用代码语法进行讲解。谢谢。 - Bashir Momen

33

我发现使用 JSON.parse(inputString) 时出现了同样的问题。

在我的情况下,输入字符串来自于服务器页的返回结果(页面方法的返回值)

我打印了 typeof(inputString),结果是字符串,但仍然出现了错误。

我还尝试了 JSON.stringify(inputString),但没有帮助。

后来我发现这是由于字段值中存在换行符操作符[\n]引起的问题。

我使用了替换(用其他字符替换,然后在解析后将换行符恢复回去),然后一切正常了。


2
换行符也是我的问题。那么我们如何恢复这样的数据呢? - kolenda
@kolenda 您的JSON无效。您需要更改服务器以使用实际的JSON序列化程序来返回有效的JSON。 - SLaks
我遇到了类似的问题,但是路径中不是"\n"而是"\e"(我更改了服务器端代码,使用"/"代替"",然后一切都正常工作了)。 - Adam Tal
使用转义字符,其中 \n 将变为 \n: - Paul Gregoire
我用 <br> 替换了它 - 对我有用 - data = data.replaceAll('\n','\u003cbr\u003e') - srashtisj

21

你应该在这里验证JSON字符串。

有效的JSON字符串必须在键周围有双引号:

JSON.parse({"u1":1000,"u2":1100})       // will be ok

如果没有引号,就会导致错误:

JSON.parse({u1:1000,u2:1100})    
// error Uncaught SyntaxError: Unexpected token u in JSON at position 2

使用单引号也会导致错误:

JSON.parse({'u1':1000,'u2':1100})    
// error Uncaught SyntaxError: Unexpected token ' in JSON at position 1

在我的情况下,Grails 2.5.6 使用单引号渲染 render ([key: value]),导致jquery Ajax中的JSON解析错误位于位置1。使用 render (groovy.json.JsonOutput.toJson ([key:value])) 解决了我的问题。 - philburns

14
products = [{"name":"Pizza","price":"10","quantity":"7"}, {"name":"Cerveja","price":"12","quantity":"5"}, {"name":"Hamburguer","price":"10","quantity":"2"}, {"name":"Fraldas","price":"6","quantity":"2"}];

改为

products = '[{"name":"Pizza","price":"10","quantity":"7"}, {"name":"Cerveja","price":"12","quantity":"5"}, {"name":"Hamburguer","price":"10","quantity":"2"}, {"name":"Fraldas","price":"6","quantity":"2"}]';

2
@SLaks 是的,OP可以直接使用产品。但是如果他想使用JSON.parse,参数需要是一个字符串。 - pktangyue
在经典 ASP 中,如果想要注释一行代码,应该怎么做因为 ' 符号是用来表示注释的? - ashish bhatt
1
@ashishbhatt 你可以使用“,然后将所有其他”更改为\“ - pktangyue
2
类似这样的 JSON.parse(products.replace(/'/g, '"')) - Chemical Programmer
它的要点是什么?结论是什么?请通过编辑(更改)您的答案进行回复,而不是在此处进行评论(不包括“编辑:”,“更新:”或类似内容 - 问题/答案应该看起来像今天写的)。 - Peter Mortensen

8

3

这是我基于之前的回复所编写的函数:在我的电脑上可以正常运行,但具体情况可能因人而异

/**
   * @description Converts a string response to an array of objects.
   * @param {string} string - The string you want to convert.
   * @returns {array} - an array of objects.
  */
function stringToJson(input) {
  var result = [];

  // Replace leading and trailing [], if present
  input = input.replace(/^\[/, '');
  input = input.replace(/\]$/, '');

  // Change the delimiter to
  input = input.replace(/},{/g, '};;;{');

  // Preserve newlines, etc. - use valid JSON
  //https://dev59.com/VmYq5IYBdhLWcg3wfwxx
  input = input.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");

  // Remove non-printable and other non-valid JSON characters
  input = input.replace(/[\u0000-\u0019]+/g, "");

  input = input.split(';;;');

  input.forEach(function(element) {
    //console.log(JSON.stringify(element));

    result.push(JSON.parse(element));
  }, this);

  return result;
}

2

在调用JSON.parse()时,可能会遇到"SyntaxError: Unexpected token"异常,其中一个原因是字符串值中包含以下内容:

  1. 换行符。

  2. 制表符(是的,就是你可以用Tab键产生的制表符!)

  3. 任何独立的反斜杠\(但由于某种原因,在Chrome上不包括/。)

(有关完整列表,请参见此处的String部分。)

例如,以下内容将导致此异常:

{
    "msg" : {
        "message": "It cannot
contain a new-line",
        "description": "Some discription with a     tabbed space is also bad",
        "value": "It cannot have 3\4 un-escaped"
    }
}

所以它应该被更改为:
{
    "msg" : {
        "message": "It cannot\ncontain a new-line",
        "description": "Some discription with a\t\ttabbed space",
        "value": "It cannot have 3\\4 un-escaped"
    }
}

我必须说,当使用较大量的文本并且仅以JSON格式显示时,这使得它相当难以阅读。


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