有没有一种简单的方法可以自定义JSON.stringify格式化数组的方式?

时间:2018-12-19 00:21:29

标签: javascript json serialization stringify

我经常想“漂亮地打印”(包括额外的空格以使人类更容易理解)JavaScript对象,而JSON.stringify(myObject, null, " ")通常就足够了。但是,在许多情况下,我确实不希望将数字数组拆分成新的行。

是否有通过native JSON.stringify function完成此操作的简单/优雅方式?

我尝试使用“替换器”功能,但这似乎仅有助于更改(例如,修改数据),过滤(例如,省略数据)和副作用(例如,日志数据),另请参见How Do I Use The Replacer Function With JSON Stringify?

或者,是否已经建立了执行此操作的模块/库/实用程序,还是我应该编写自己的模块/库/实用程序?

似乎有many search results on npm.org for "stringify",但我看到的似乎只是可以在特定问题域上更有效地运行或避免与循环/循环数据结构相关的问题的变体。

const obj = {
  foo: "bar",
  oneLine: [1,2,3],
  multipleLines: [{
    name: "X",
    alsoOneLine: [4,5,6]
  }, {
    name: "Y"
  }]
};

document.write(`
  <pre>
    // This isn't the output I want. 
    // The arrays containing only numbers should have their elements
    // all printed on the same line.
    ${JSON.stringify(obj, null, "  ")}
  </pre>
`);

1 个答案:

答案 0 :(得分:2)

您可以使用正则表达式在字符串化版本中搜索数字数组,然后将所有这些数字数组中的空格替换为空字符串。通过使用^将模式的开头锚定到行的开头,可以确保匹配的键值对(如果数字数组包含在另一个数组中,则为纯值)是 array ,而不是其他内容,例如包含看起来像JSON-array-of-numbers的字符串:

const obj = {
  foo: "bar",
  oneLine: [1, 2, 3],
  multipleLines: [{
    name: "X",
    alsoOneLine: [4, 5, 6],
    inner: [
      [1, 2, 3],
      [4, 5, 6]
    ]
  }, {
    name: "Y"
  }]
};

const stringified = JSON.stringify(obj, null, "  ");
const numArraysOnOneLine = stringified.replace(
  /^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])/gm,
  (_, leadingWhitespace, possibleKeyStr='', arrStr) => (
    leadingWhitespace + possibleKeyStr + arrStr.replace(/\s+/g, ''
  ))
);
document.write(`<pre>${numArraysOnOneLine}</pre>`);

https://regex101.com/r/XfuqoT/1

图案

^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])

表示:

  • ^-匹配一行的开头
  • ( *)第一个捕获组:捕获前导空白
  • ("[^"]+": )?第二组,可选:如果数组包含在对象中,则匹配双引号键
  • \[-第三组的开头。匹配文字[
  • (?:\s+\d+,)*-重复一组空格字符,然后将数字重复零次或多次
  • \s+\d+\s+-匹配数组中的最后一项(无尾部逗号):空格,后跟一个数字,然后是更多的空格
  • \]-之后是终止的](第三组结尾)

如果数字也可以包含小数,则将\d+替换为\d+(?:\.\d+)?,以允许可选的十进制数字。

如果对象属性也可能包含双引号(在字符串化时由反斜杠转义),则将[^"]+替换为(?:[^"]|\\")+ https://regex101.com/r/XfuqoT/2