使用节点将字符串解析为 JSON 会产生意外的令牌,验证器说没问题

Posted

技术标签:

【中文标题】使用节点将字符串解析为 JSON 会产生意外的令牌,验证器说没问题【英文标题】:Parsing string to JSON using node gives unexpected token, validator says ok 【发布时间】:2014-04-08 00:33:00 【问题描述】:

我想将以下字符串解析为 JSON:


    "STATUS": [
        
            "STATUS": "S",
            "When": 1394044643,
            "Code": 17,
            "Msg": "GPU0",
            "Description": "cgminer 3.7.3"
        
    ],
    "GPU": [
        
            "GPU": 0,
            "Enabled": "Y",
            "Status": "Alive",
            "Temperature": 70,
            "Fan Speed": 3089,
            "Fan Percent": 70,
            "GPU Clock": 1180,
            "Memory Clock": 1500,
            "GPU Voltage": 1.206,
            "GPU Activity": 99,
            "Powertune": 20,
            "MHS av": 0.4999,
            "MHS 5s": 0.5009,
            "Accepted": 4335,
            "Rejected": 7,
            "Hardware Errors": 0,
            "Utility": 27.8007,
            "Intensity": "0",
            "Last Share Pool": 0,
            "Last Share Time": 1394044643,
            "Total MH": 4676.7258,
            "Diff1 Work": 69436,
            "Difficulty Accepted": 69360,
            "Difficulty Rejected": 112,
            "Last Share Difficulty": 16,
            "Last Valid Work": 1394044643,
            "Device Hardware%": 0,
            "Device Rejected%": 0.1613,
            "Device Elapsed": 9356
        
    ],
    "id": 1

当我使用例如http://jsonlint.com/ 它说 JSON 是正确的,但是当我在 node.js 中使用时:

console.log(JSON.parse(data.toString()));

我得到以下信息:

undefined:1
e Hardware%":0.0000,"Device Rejected%":0.1570,"Device Elapsed":9554],"id":1
                                                                             ^
SyntaxError: Unexpected token

任何线索我在这里做错了什么?

编辑

数据以 ByteStream 的形式出现:

.on('data',function(data)
  console.log(data.toString());
  console.log();
  console.log(data);
  console.log();
  console.log("data "+ data.GPU);
  //...

//...
"STATUS":["STATUS":"S","When":1394045650,"Code":17,"Msg":"GPU0","Description":"cgminer 3.7.3"],"GPU":["GPU":0,"Enabled":"Y","Status":"Alive","Temperature":70.00,"Fan Speed":3090,"Fan Percent":70,"GPU Clock":1180,"Memory Clock":1500,"GPU Voltage":1.206,"GPU Activity":99,"Powertune":20,"MHS av":0.4999,"MHS 5s":0.5007,"Accepted":4841,"Rejected":8,"Hardware Errors":0,"Utility":28.0261,"Intensity":"0","Last Share Pool":0,"Last Share Time":1394045638,"Total MH":5181.3734,"Diff1 Work":77548,"Difficulty Accepted":77456.00000000,"Difficulty Rejected":128.00000000,"Last Share Difficulty":16.00000000,"Last Valid Work":1394045638,"Device Hardware%":0.0000,"Device Rejected%":0.1651,"Device Elapsed":10364],"id":1 

<Buffer 7b 22 53 54 41 54 55 53 22 3a 5b 7b 22 53 54 41 54 55 53 22 3a 22 53 22 2c 22 57 68 65 6e 22 3a 31 33 39 34 30 34 35 32 34 38 2c 22 43 6f 64 65 22 3a 31 ...>

data undefined

编辑

当我这样做时:

console.log(data.toString());
console.log(JSON.stringify(data.toString()));

我得到以下结果:

""STATUS":["STATUS":"S","When":1394046864,"Code":17,"Msg":"GPU0","Description":"cgminer 3.7.3"],"GPU":["GPU":0,"Enabled":"Y","Status":"Alive","Temperature":70.00,"Fan Speed":3087,"Fan Percent":70,"GPU Clock":1180,"Memory Clock":1500,"GPU Voltage":1.206,"GPU Activity":99,"Powertune":20,"MHS av":0.5000,"MHS 5s":0.5016,"Accepted":5396,"Rejected":8,"Hardware Errors":0,"Utility":27.9597,"Intensity":"0","Last Share Pool":0,"Last Share Time":1394046864,"Total MH":5789.2352,"Diff1 Work":86428,"Difficulty Accepted":86336.00000000,"Difficulty Rejected":128.00000000,"Last Share Difficulty":16.00000000,"Last Valid Work
":1394046864,"Device Hardware%":0.0000,"Device Rejected%":0.1481,"Device Elapsed":11580],"id":1"
"\"STATUS\":[\"STATUS\":\"S\",\"When\":1394046864,\"Code\":17,\"Msg\":\"GPU0\",\"Description\":\"cgminer 3.7.3\"],\"GPU\":[\"GPU\":0,\"Enabled\":\"Y\",\"Status\":\"Alive\",\"Temperature\":70.00,\"Fan Sp
eed\":3087,\"Fan Percent\":70,\"GPU Clock\":1180,\"Memory Clock\":1500,\"GPU Voltage\":1.206,\"GPU Activity\":99,\"Powertune\":20,\"MHS av\":0.5000,\"MHS 5s\":0.5016,\"Accepted\":5396,\"Rejected\":8,\"Hardw
are Errors\":0,\"Utility\":27.9597,\"Intensity\":\"0\",\"Last Share Pool\":0,\"Last Share Time\":1394046864,\"Total MH\":5789.2352,\"Diff1 Work\":86428,\"Difficulty Accepted\":86336.00000000,\"Difficulty Re
jected\":128.00000000,\"Last Share Difficulty\":16.00000000,\"Last Valid Work\":1394046864,\"Device Hardware%\":0.0000,\"Device Rejected%\":0.1481,\"Device Elapsed\":11580],\"id\":1\u0000"

注意第二条消息 \u0000 的最后一个 unicode 字符,我可以用它做什么?

【问题讨论】:

data 已经是一个 JSON 对象。您将其转换为带有 toString() 的字符串,然后立即将其解析回 JSON...只需按原样使用 data @AndréDion:如果是 JSON,它是一个字符串,尽管它可能是一个 String 对象包装器。使用.toString() 是无害的。而JSON.parse 不会将其转回 JSON。它接受 JSON 并将其转换为 javascript 对象。 @cookiemonster JSON 不是字符串。它是对象文字的更严格的子集。 JSON.parse 接受一个字符串并转换为一个真正的对象字面量。 你能发布更多代码吗?您确定这是您收到的准确响应吗? 您能否发布整个Buffer 输出。现在它跟在... 【参考方案1】:

问题在于终止空字符。删除它后,我现在可以毫无问题地解析字符串(如果有的话,发布更有效的方法)

var re = /\0/g;
str = data.toString().replace(re, "");
var o = JSON.parse(str);
console.log(o);

var str = data.toString().slice(0, - 1);

或者直接处理Buffer中的字节

var buf = data.slice(0,data.length-1);
console.log(JSON.parse(buf.toString()));

【讨论】:

这对我有用,字符串是从 java 传递的,传输附加了一个 null【参考方案2】:

我为 data.toString() 复制了您的控制台日志输出,并且正如@patryk 指出的那样,字符串末尾有一个 unicode 字符 \u0000。这可能是导致问题的原因。我删除了尾随字符,将字符串分配给一个变量,并从中创建了一个缓冲区,一切都很好。

var a = '"STATUS":["STATUS":"S","When":1394045650,"Code":17,"Msg":"GPU0","Description":"cgminer 3.7.3"],"GPU":["GPU":0,"Enabled":"Y","Status":"Alive","Temperature":70.00,"Fan Speed":3090,"Fan Percent":70,"GPU Clock":1180,"Memory Clock":1500,"GPU Voltage":1.206,"GPU Activity":99,"Powertune":20,"MHS av":0.4999,"MHS 5s":0.5007,"Accepted":4841,"Rejected":8,"Hardware Errors":0,"Utility":28.0261,"Intensity":"0","Last Share Pool":0,"Last Share Time":1394045638,"Total MH":5181.3734,"Diff1 Work":77548,"Difficulty Accepted":77456.00000000,"Difficulty Rejected":128.00000000,"Last Share Difficulty":16.00000000,"Last Valid Work":1394045638,"Device Hardware%":0.0000,"Device Rejected%":0.1651,"Device Elapsed":10364],"id":1';

var b = new Buffer(a);

console.log(JSON.parse(b.toString());

输出 -

 STATUS: 
   [  STATUS: 'S',
       When: 1394045650,
       Code: 17,
       Msg: 'GPU0',
       Description: 'cgminer 3.7.3'  ],
  GPU: 
   [  GPU: 0,
       Enabled: 'Y',
       Status: 'Alive',
       Temperature: 70,
       'Fan Speed': 3090,
       'Fan Percent': 70,
       'GPU Clock': 1180,
       'Memory Clock': 1500,
       'GPU Voltage': 1.206,
       'GPU Activity': 99,
       Powertune: 20,
       'MHS av': 0.4999,
       'MHS 5s': 0.5007,
       Accepted: 4841,
       Rejected: 8,
       'Hardware Errors': 0,
       Utility: 28.0261,
       Intensity: '0',
       'Last Share Pool': 0,
       'Last Share Time': 1394045638,
       'Total MH': 5181.3734,
       'Diff1 Work': 77548,
       'Difficulty Accepted': 77456,
       'Difficulty Rejected': 128,
       'Last Share Difficulty': 16,
       'Last Valid Work': 1394045638,
       'Device Hardware%': 0,
       'Device Rejected%': 0.1651,
       'Device Elapsed': 10364  ],
  id: 1 

【讨论】:

JSON 允许前导和尾随空格。 JSON.parse(' \n\n\t\t "foo":"bar" \n\n\t\t ') JSON 在带引号的字符串之外完全不区分空格。 我没有在十六进制编辑器中检查字符串。也许是一些非法的隐形字符 相应地编辑了答案

以上是关于使用节点将字符串解析为 JSON 会产生意外的令牌,验证器说没问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSON.parse 方法解析数据时 JSON 中位置 0 错误的意外令牌'

解析 JSON 给出“意外的令牌 o”错误 [重复]

Javascript - 去掉 JSON 字符串中出现的 u',解析返回意外令牌

使用节点将令牌保存在本地存储中

如何使用节点将表单数据(文本/纯文本)转换为 json?

如何使用节点将用户数据对象与令牌一起发送到角度前端?