【问题标题】:Line-length based custom python JSON encoding for serializables用于可序列化的基于行长的自定义 python JSON 编码
【发布时间】:2017-06-29 20:33:51
【问题描述】:

我的问题与Can I implement custom indentation for pretty-printing in Python’s JSON module?How to change json encoding behaviour for serializable python object? 类似,但是如果整个 JSON 编码结构可以在 Python 2.X 和 3 中以可配置的行长容纳在该单行上,我想将行折叠在一起。X。输出用于 JSON 结构的易于阅读的文档,而不是调试。澄清:结果必须是有效的 JSON,并允许 OrderedDicts/sort_keys、默认处理程序等的常规 JSON 编码功能。

custom indentation 的解决方案不适用,因为各个结构需要提前知道它们的序列化长度,因此添加 NoIndent 类无济于事,因为每个结构可能会或可能不会缩进。 changing the behavior of json serializable 的解决方案不适用,因为数据结构上没有任何(奇怪的)自定义覆盖,它们只是常规列表和字典。

例如,而不是:

{
  "@context": "http://linked.art/ns/context/1/full.jsonld", 
  "id": "http://lod.example.org/museum/ManMadeObject/0", 
  "type": "ManMadeObject", 
  "classified_as": [
    "aat:300033618", 
    "aat:300133025"
  ]
}

我想制作:

{
  "@context": "http://linked.art/ns/context/1/full.jsonld", 
  "id": "http://lod.example.org/museum/ManMadeObject/0", 
  "type": "ManMadeObject", 
  "classified_as": ["aat:300033618", "aat:300133025"]
}

在结构内的任何级别的嵌套中,以及跨越任意数量的嵌套级别,直到达到行长。因此,如果有一个列表,里面有一个对象,一个键/值对,它会变成:

{
  "@context": "http://linked.art/ns/context/1/full.jsonld", 
  "id": "http://lod.example.org/museum/ManMadeObject/0", 
  "type": "ManMadeObject", 
  "classified_as": [{"id": "aat:300033618"}]
}

按照@robm 对custom indentation 的方法,缩进输出上的递归下降解析器似乎可以工作,但复杂性似乎很快接近编写JSON 解析器和序列化程序的复杂性。 否则,似乎需要一个非常自定义的 JSONEncoder。

感谢您的想法!

【问题讨论】:

  • 你用过pprint 吗?它适用于 python2 和 3
  • @ChihebNexus 是的,但是对于具有多个键的字典,它不能按预期工作。
  • pprint 不起作用,因为结果不一定是有效的 JSON。
  • @Coldspeed,对于pprint 的默认行为,我认为它做得很好。看这里https://repl.it/JHzW/0
  • @RobSanderson 如果您愿意接受pprint 的输出,这实际上是可以补救的。

标签: python json


【解决方案1】:

非常低效,但目前看来还有效:

def _collapse_json(text, collapse):
    js_indent = 2
    lines = text.splitlines()
    out = [lines[0]]
    while lines:
        l = lines.pop(0)
        indent = len(re.split('\S', l, 1)[0])
        if indent and l.rstrip()[-1] in ['[', '{']:
            curr = indent
            temp = []
            stemp = []
            while lines and curr <= indent:
                if temp and curr == indent:
                    break
                temp.append(l[curr:])
                stemp.append(l.strip())
                l = lines.pop(0)
                indent = len(re.split('\S', l, 1)[0])                   
            temp.append(l[curr:])
            stemp.append(l.lstrip())

            short = " " * curr + ''.join(stemp)
            if len(short) < collapse:
                out.append(short)
            else:
                ntext = '\n'.join(temp)
                nout = _collapse_json(ntext, collapse)                  
                for no in nout:
                    out.append(" " * curr + no)
                l = lines.pop(0)
        elif indent:
            out.append(l)
    out.append(l)
    return out

def collapse_json(text, collapse):
    return '\n'.join(_collapse_json(text, collapse))

很高兴接受产生相同输出而不不断上下爬行的其他东西!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 2012-10-22
    相关资源
    最近更新 更多