在一行上格式化某些JSON对象

Tim*_*lds 5 python formatting json python-3.x

考虑以下代码:

>>> import json
>>> data = {
...     'x': [1, {'$special': 'a'}, 2],
...     'y': {'$special': 'b'},
...     'z': {'p': True, 'q': False}
... }
>>> print(json.dumps(data, indent=2))
{
  "y": {
    "$special": "b"
  },
  "z": {
    "q": false,
    "p": true
  },
  "x": [
    1,
    {
      "$special": "a"
    },
    2
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想要的是格式化JSON,以便仅具有单个属性的JSON对象'$special'在一行上呈现,如下所示。

{
  "y": {"$special": "b"},
  "z": {
    "q": false,
    "p": true
  },
  "x": [
    1,
    {"$special": "a"},
    2
  ]
}
Run Code Online (Sandbox Code Playgroud)

我玩过实现自定义JSONEncoder并将其json.dumps作为cls参数传递给我的方法,但是JSONEncoder每个方法都有两个问题:

  • JSONEncoder default方法是针对的每个部分调用的data,但是返回值不是原始的JSON字符串,因此似乎没有任何方法可以调整其格式。

  • JSONEncoder encode方法的确返回了原始的JSON字符串,但data整个方法仅被调用一次。

有什么办法可以JSONEncoder做我想做的事吗?

Tim*_*lds 1

我发现以下基于正则表达式的解决方案是最简单的,尽管……基于正则表达式

import json
import re
data = {
    'x': [1, {'$special': 'a'}, 2],
    'y': {'$special': 'b'},
    'z': {'p': True, 'q': False}
}
text = json.dumps(data, indent=2)
pattern = re.compile(r"""
{
\s*
"\$special"
\s*
:
\s*
"
((?:[^"]|\\"))*  # Captures zero or more NotQuote or EscapedQuote
"
\s*
}
""", re.VERBOSE)
print(pattern.sub(r'{"$special": "\1"}', text))
Run Code Online (Sandbox Code Playgroud)

输出如下。

{
  "x": [
    1,
    {"$special": "a"},
    2
  ],
  "y": {"$special": "b"},
  "z": {
    "q": false,
    "p": true
  }
}
Run Code Online (Sandbox Code Playgroud)