javascript - 当 JSON 太长时 JSON.parse() 会抛出错误

标签 javascript node.js json

我在node.js 中生成了一个返回JSON 数据的python child_process。在我的 python 文件中,我在将其传回 Node 之前使用了 json.dumps() 。 每当 JSON 中的列表“结果”包含超过 62 个条目时,我的 Node.js 服务器在尝试解析它时就会崩溃。否则一切正常吗?

即使 Node 应用程序终止,数据仍会正确发送回客户端。

只有在调用 JSON.parse() 时才会抛出错误消息,但我不能在这里忽略它,因为从 python 接收到的数据是缓冲格式的:

<Buffer 7b 0d 0a 20 20 22 70 61 72 61 6d 65 74 65 72 73 22 3a 20 5b 0d 0a 20 20 20 20 7b 0d 0a 20 20 20 20 20 20 22 70 72 6f 70 65 72 74 79 22 3a 20 22 42 65 ... 9136 more bytes>
<Buffer 0d 0a>

有人知道问题出在哪里吗?

抛出的错误消息是:

undefined:2

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at Socket.<anonymous> (D:\Projects\data-farming-framework-api\app.js:52:23)

    at Socket.emit (events.js:310:20)
    at addChunk (_stream_readable.js:286:12)
    at readableAddChunk (_stream_readable.js:268:9)
    at Socket.Readable.push (_stream_readable.js:209:10)
    at Pipe.onStreamRead (internal/stream_base_commons.js:186:23)

我的node.js代码:

app.post('/api/ps/executeExperiments', async (req, res, next) => {
  let path = req.body.path;
  let experiments = JSON.stringify(req.body.data);
  let python = await spawn('python', ['./plantsim.py', 'execute_experiments()', path, experiments]);
  python.stdout.on('data', data => {
    if (data.toString() == 'ERROR') {
      callback(new Error('ERROR'))
    }
    let result = JSON.parse(data);
    res.send(result);
  });
});

返回的 JSON 具有以下格式:

{
  parameters: [
    { property: 'Bearbeitungszeit', object: 'Einzelstation' },
    { property: 'Bearbeitungszeit', object: 'Einzelstation2' }
  ],
  results: [
    { id: 1, input: 252, output: 249, values: [Array] },
    { id: 2, input: 198, output: 195, values: [Array] },
    { id: 3, input: 165, output: 162, values: [Array] },
    { id: 4, input: 204, output: 201, values: [Array] },
    { id: 5, input: 169, output: 166, values: [Array] },
    { id: 6, input: 239, output: 236, values: [Array] },
    { id: 7, input: 225, output: 222, values: [Array] },
    { id: 8, input: 312, output: 309, values: [Array] },
    { id: 9, input: 324, output: 321, values: [Array] },
    { id: 10, input: 248, output: 245, values: [Array] },
    { id: 11, input: 199, output: 196, values: [Array] },
    { id: 12, input: 186, output: 183, values: [Array] },
    { id: 13, input: 161, output: 158, values: [Array] },
    { id: 14, input: 149, output: 146, values: [Array] },
    { id: 15, input: 175, output: 172, values: [Array] },
    { id: 16, input: 201, output: 198, values: [Array] },
    { id: 17, input: 242, output: 239, values: [Array] },
    { id: 18, input: 162, output: 159, values: [Array] },
    { id: 19, input: 184, output: 181, values: [Array] },
    { id: 20, input: 157, output: 154, values: [Array] },
    { id: 21, input: 160, output: 157, values: [Array] },
    { id: 22, input: 290, output: 287, values: [Array] },
    { id: 23, input: 358, output: 355, values: [Array] },
    { id: 24, input: 153, output: 150, values: [Array] },
    { id: 25, input: 155, output: 152, values: [Array] },
    { id: 26, input: 195, output: 192, values: [Array] },
    { id: 27, input: 174, output: 171, values: [Array] },
    { id: 28, input: 269, output: 266, values: [Array] },
    { id: 29, input: 341, output: 338, values: [Array] },
    { id: 30, input: 263, output: 260, values: [Array] },
    { id: 31, input: 156, output: 153, values: [Array] },
    { id: 32, input: 167, output: 164, values: [Array] },
    { id: 33, input: 295, output: 292, values: [Array] },
    { id: 34, input: 230, output: 227, values: [Array] },
    { id: 35, input: 189, output: 186, values: [Array] },
    { id: 36, input: 172, output: 169, values: [Array] },
    { id: 37, input: 254, output: 251, values: [Array] },
    { id: 38, input: 182, output: 179, values: [Array] },
    { id: 39, input: 206, output: 203, values: [Array] },
    { id: 40, input: 232, output: 229, values: [Array] },
    { id: 41, input: 259, output: 256, values: [Array] },
    { id: 42, input: 159, output: 156, values: [Array] },
    { id: 43, input: 305, output: 302, values: [Array] },
    { id: 44, input: 151, output: 148, values: [Array] },
    { id: 45, input: 181, output: 178, values: [Array] },
    { id: 46, input: 302, output: 299, values: [Array] },
    { id: 47, input: 187, output: 184, values: [Array] },
    { id: 48, input: 245, output: 242, values: [Array] },
    { id: 49, input: 149, output: 146, values: [Array] },
    { id: 50, input: 279, output: 276, values: [Array] },
    { id: 51, input: 215, output: 212, values: [Array] },
    { id: 52, input: 170, output: 167, values: [Array] },
    { id: 53, input: 288, output: 285, values: [Array] },
    { id: 54, input: 329, output: 326, values: [Array] },
    { id: 55, input: 283, output: 280, values: [Array] },
    { id: 56, input: 193, output: 190, values: [Array] },
    { id: 57, input: 177, output: 174, values: [Array] },
    { id: 58, input: 348, output: 345, values: [Array] },
    { id: 59, input: 265, output: 262, values: [Array] },
    { id: 60, input: 219, output: 216, values: [Array] },
    { id: 61, input: 352, output: 349, values: [Array] },
    { id: 62, input: 151, output: 148, values: [Array] }
  ]
}

Values 也是一个列表,但是我不知道为什么它没有正确显示在终端中。当数据正确传递给客户端时,数据仍然存在。

最佳答案

data 事件在任意边界上传递数据 block 。只要您将整个 JSON 放在一个 block 中(这是您无法控制的),您的代码就可能恰好可以工作。但是,一旦数据变得足够大,需要足够长的时间来生成它,并且它会以多个 block 的形式发送,那么您的代码就会在尝试解析单个数据 block 时崩溃。这就是为什么它依赖于尺寸。当数据达到一定大小时,它将开始以多个 block 的形式到达。而且,您无法将每个 block 单独解析为 JSON(因此会出现 JSON.parse() 错误。

相反,如果您要将其解析为 JSON,则需要累积所有 block ,然后在完成后解析整个内容。 JSON不是一种可以轻松增量解析的格式(有JSON流代码可以做到这一点,但工作量很大)。

app.post('/api/ps/executeExperiments', async (req, res, next) => {
  let path = req.body.path;
  let experiments = JSON.stringify(req.body.data);
  let python = spawn('python', ['./plantsim.py', 'execute_experiments()', path, experiments]);

  let allData = [];
  // collect from all the data events here
  python.stdout.on('data', data => {
    allData.push(data.toString());
  }).on('error', e => {
     console.log(e);
     res.sendStatus(500);
  }).on('close', () => {
     // we have all data now
     let result = allData.join(allData, "");
     if (result.startsWith('ERROR')) {
        console.log(result);
        res.sendStatus(500);
     } else {
        res.send(allData);
     }
  });
});

在您现有的代码中,callback() 是什么?你没有展示这一点,这让我很困惑,所以我删除了它。

如果出现错误,您还需要向传入的 POST 请求发送错误响应。

而且,对 spawn() 的返回值使用 await 是没有意义的。它不会返回 promise ,因此 await 不会做任何有用的事情。

此外,似乎甚至不需要解析 JSON。如果您只想解析它,然后使用 res.send() 立即发送它,则 res.send() 要做的就是将其返回再次转换为 JSON。那么,也许您真正需要做的只是将 python.stdout 流作为您的响应?

关于javascript - 当 JSON 太长时 JSON.parse() 会抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61715218/

相关文章:

node.js - 从路由器发布响应中检索键值?

c# - 从 asp.net 网页中的 jQuery Ajax 调用检索 JSON 数组

c# - jQuery - 如何正确显示两个日期之间的所有记录?

javascript - HTML5 视频 : canPlayType() is not working in safari

javascript - 获取随机 Discord 用户

jquery - 为什么 JSON.stringify() 不将数据传递给 $.cookie()

json - 是否有其他方法可以将 JSON 响应转换为自定义 Dart 对象?

javascript - Bootstrap 模式显示和隐藏奇怪的行为

javascript - 如何自定义(或禁用)JQueryMobile 中的自动 "back"按钮

javascript - jade中继承模板的修改