如何将无法预测的JSON解析为字符串? [英] How do I parse JSON sprinkled unpredictably into a string?

查看:89
本文介绍了如何将无法预测的JSON解析为字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个node.js应用程序,该应用程序以一种奇怪的格式接收输入:将带有JSON的字符串任意撒入其中,就像这样:

Suppose that I've got a node.js application that receives input in a weird format: strings with JSON arbitrarily sprinkled into them, like so:

This is a string {"with":"json","in":"it"} followed by more text {"and":{"some":["more","json"]}} and more text

对于此输入文本,我有一些保证:

I have a couple guarantees about this input text:

  1. JSON对象之间的文字文本始终没有花括号.

  1. The bits of literal text in between the JSON objects are always free from curly braces.

推入文本中的顶级JSON对象始终是对象文字,而不是数组.

The top level JSON objects shoved into the text are always object literals, never arrays.

我的目标是将其拆分为一个数组,使文字文本保留下来,并解析出JSON,如下所示:

My goal is to split this into an array, with the literal text left alone and the JSON parsed out, like this:

[
    "This is a string ",
    {"with":"json","in":"it"},
    " followed by more text ",
    {"and":{"some":["more","json"]}},
    " and more text"
]

到目前为止,我已经编写了一个天真的解决方案,该解决方案仅对大括号进行计数即可确定JSON的起始位置然后停下来.但是,如果JSON包含{"like":"this one } right here"}中带有花括号的字符串,则此方法将无效.我可以尝试通过类似的报价计算数学来解决该问题,但随后我还必须考虑转义的报价.到那时,感觉像是我在重做JSON.parse的工作.有解决这个问题的更好方法吗?

So far I've written a naive solution that simply counts curly braces to decide where the JSON starts and stops. But this wouldn't work if the JSON contains strings with curly braces in them {"like":"this one } right here"}. I could try to get around that by doing similar quote counting math, but then I also have to account for escaped quotes. At that point it feels like I'm redoing way too much of JSON.parse's job. Is there a better way to solve this problem?

推荐答案

这是一种相对简单的蛮力方法:在花括号上分割整个输入字符串,然后按顺序遍历数组.每当遇到开放括号时,从该起点查找成功解析为JSON的数组中最长的块.冲洗并重复.

Here's a comparatively simple brute-force approach: split the whole input string on curly braces, then step through the array in order. Whenever you come across an open brace, find the longest chunk of the array from that starting point that successfully parses as JSON. Rinse and repeat.

如果输入包含无效的JSON和/或不平衡的括号,这将起作用(请参见下面的最后两个测试用例.)

This will not work if the input contains invalid JSON and/or unbalanced braces (see the last two test cases below.)

const tryJSON = input => {
  try {
    return JSON.parse(input);
  } catch (e) {
    return false;
  }
}

const parse = input => {
  let output = [];
  let chunks = input.split(/([{}])/);

  for (let i = 0; i < chunks.length; i++) {
    if (chunks[i] === '{') {
      // found some possible JSON; start at the last } and backtrack until it works.
      for (let j = chunks.lastIndexOf('}'); j > i; j--) {
        if (chunks[j] === '}') {
          // Does it blend?
          let parsed = tryJSON(chunks.slice(i, j + 1).join(""))
          if (parsed) {
            // it does! Grab the whole thing and skip ahead
            output.push(parsed);
            i = j;
          }
        }
      }
    } else if (chunks[i]) {
      // neither JSON nor empty
      output.push(chunks[i])
    }
  }

  console.log(output)
  return output
}

parse(`{"foo": "bar"}`)
parse(`test{"foo": "b}ar{{[[[{}}}}{}{}}"}`)
parse(`this {"is": "a st}ri{ng"} with {"json": ["in", "i{t"]}`)
parse(`{}`)
parse(`this {"i{s": invalid}`)
parse(`So is {this: "one"}`)

这篇关于如何将无法预测的JSON解析为字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆