用于序列化的基于行长的自定义python JSON编码

2024-10-02 20:36:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我的问题类似于Can I implement custom indentation for pretty-printing in Python’s JSON module?How to change json encoding behaviour for serializable python object?,但是如果整个JSON编码的结构可以放在python2.X和3.X中的那一行上,并且具有可配置的行长,那么我希望将行折叠在一起。输出的目的是使JSON结构的文档易于阅读,而不是调试。澄清:结果必须是有效的JSON,并允许orderedicts/sort\u键、默认处理程序等常规JSON编码特性

来自custom indentation的解决方案不适用,因为单个结构需要提前知道它们的序列化长度,因此添加NoIndent类没有帮助,因为每个结构都可能缩进,也可能没有缩进。来自changing the behavior of json serializable的解决方案不适用,因为数据结构上没有任何(奇怪的)自定义重写,它们只是常规列表和dict

例如,而不是:

{
  "@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

感谢您的想法


Tags: idjsonhttpcustomcontext结构fullns
1条回答
网友
1楼 · 发布于 2024-10-02 20:36:44

效率很低,但到目前为止似乎有效:

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))

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

相关问题 更多 >