用标签作为json倾倒山药

发布于 2025-01-31 09:11:46 字数 792 浏览 5 评论 0原文

我知道我可以使用ruamel.yaml加载一个带有标签的文件。但是,当我想在没有它们的情况下倾倒时,我会遇到错误。简化示例: -

from ruamel.yaml import YAML
from json import dumps
import sys

yaml = YAML()
data = yaml.load(
"""
!mytag
a: 1
b: 2
c: 2022-05-01
"""
)

try:
    yaml2 = YAML(typ='safe', pure=True)
    yaml.default_flow_style = True
    yaml2.dump(data, sys.stdout)
except Exception as e:
    print('exception dumping using yaml', e)
try:
    print(dumps(data))
except Exception as e:
    print('exception dumping using json', e)

使用使用的异常倾倒不能表示对象:orderedDict([('a',1),('b',2),('c',dateTime.date.date(2022,5,1))])

使用类型日期的JSON对象的异常转储不是JSON序列化

我不能在标签上出现错误的情况下更改load()。如何使用剥离标签(YAML或JSON)获取输出?

I know I can use ruamel.yaml to load a file with tags in it. But when I want to dump without them i get an error. Simplified example :-

from ruamel.yaml import YAML
from json import dumps
import sys

yaml = YAML()
data = yaml.load(
"""
!mytag
a: 1
b: 2
c: 2022-05-01
"""
)

try:
    yaml2 = YAML(typ='safe', pure=True)
    yaml.default_flow_style = True
    yaml2.dump(data, sys.stdout)
except Exception as e:
    print('exception dumping using yaml', e)
try:
    print(dumps(data))
except Exception as e:
    print('exception dumping using json', e)

exception dumping using cannot represent an object: ordereddict([('a', 1), ('b', 2), ('c', datetime.date(2022, 5, 1))])

exception dumping using json Object of type date is not JSON serializable

I cannot change the load() without getting an error on the tag. How to get output with tags stripped (YAML or JSON)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月寒剑心 2025-02-07 09:11:46

您会遇到错误,因为安全的笨拙(纯净)和JSON都不知道ruamel.yaml内部
保留注释,标记,块/流风格等的类型。

将作为yaml的转储,您可以使用替代转储方法注册这些类型。作为JSON,这更复杂
作为afaik,您只能转换叶子节点(即YAML标量,您将是
能够使用它来倾倒dateTime.dateTime实例,该实例被加载为键c的值)。

我已经使用yaml作为可读,可编辑和编程性更新的配置文件
如果其文件不老于相应的yaml,则使用的数据的加载速度更快(如果
它是较旧的JSON从YAML创建的)。为了dump(s)
递归产生JSON理解的Python原语。

以下是这样做的,但是除了DateTime以外还有其他构造
JSON不允许的实例。例如,使用序列或dict
如钥匙(在YAML中允许,但在JSON中不允许)。对于钥匙
序列我将元素的字符串表示串联

from ruamel.yaml import YAML
import sys
import datetime
import json
from collections.abc import Mapping

yaml = YAML()
data = yaml.load("""\
!mytag
a: 1
b: 2
c: 2022-05-01
[d, e]: !myseq [42, 196]
{f: g, 18: y}: !myscalar x
""")

def json_dump(data, out, indent=None):
    def scalar(obj):
        if obj is None:
            return None
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return str(obj)
        if isinstance(obj, ruamel.yaml.scalarbool.ScalarBoolean):
            return obj == 1
        if isinstance(obj, bool):
            return bool(obj)
        if isinstance(obj, int):
            return int(obj)
        if isinstance(obj, float):
            return float(obj)
        if isinstance(obj, tuple):
            return '_'.join([str(x) for x in obj])
        if isinstance(obj, Mapping):
            return '_'.join([f'{k}-{v}' for k, v in obj.items()])
        if not isinstance(obj, str): print('type', type(obj))
        return obj

    def prep(obj):
        if isinstance(obj, dict):
            return {scalar(k): prep(v) for k, v in obj.items()}
        if isinstance(obj, list):
            return [prep(elem) for elem in obj]
        if isinstance(obj, ruamel.yaml.comments.TaggedScalar):
            return prep(obj.value)
        return scalar(obj)

    res = prep(data)
    json.dump(res, out, indent=indent)


json_dump(data, sys.stdout, indent=2)

给出:

{
  "a": 1,
  "b": 2,
  "c": "2022-05-01",
  "d_e": [
    42,
    196
  ],
  "f-g_18-y": "x"
}

You get the error because the neither the safe dumper (pure or not), nor JSON, do know about the ruamel.yaml internal
types that preserve comments, tagging, block/flow-style, etc.

Dumping as YAML, you could register these types with alternate dump methods. As JSON this is more complex
as AFAIK you can only convert the leaf-nodes (i.e. the YAML scalars, you would e.g. be
able to use that to dump the datetime.datetime instance that is loaded as the value of key c).

I have used YAML as a readable, editable and programmatically updatable config file with
an much faster loading JSON version of the data used if its file is not older than the corresponding YAML (if
it is older JSON gets created from the YAML). The thing to do in order to dump(s) is
recursively generate Python primitives that JSON understands.

The following does so, but there are other constructs besides datetime
instances that JSON doesn't allow. E.g. when using sequences or dicts
as keys (which is allowed in YAML, but not in JSON). For keys that are
sequences I concatenate the string representation of the elements
:

from ruamel.yaml import YAML
import sys
import datetime
import json
from collections.abc import Mapping

yaml = YAML()
data = yaml.load("""\
!mytag
a: 1
b: 2
c: 2022-05-01
[d, e]: !myseq [42, 196]
{f: g, 18: y}: !myscalar x
""")

def json_dump(data, out, indent=None):
    def scalar(obj):
        if obj is None:
            return None
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return str(obj)
        if isinstance(obj, ruamel.yaml.scalarbool.ScalarBoolean):
            return obj == 1
        if isinstance(obj, bool):
            return bool(obj)
        if isinstance(obj, int):
            return int(obj)
        if isinstance(obj, float):
            return float(obj)
        if isinstance(obj, tuple):
            return '_'.join([str(x) for x in obj])
        if isinstance(obj, Mapping):
            return '_'.join([f'{k}-{v}' for k, v in obj.items()])
        if not isinstance(obj, str): print('type', type(obj))
        return obj

    def prep(obj):
        if isinstance(obj, dict):
            return {scalar(k): prep(v) for k, v in obj.items()}
        if isinstance(obj, list):
            return [prep(elem) for elem in obj]
        if isinstance(obj, ruamel.yaml.comments.TaggedScalar):
            return prep(obj.value)
        return scalar(obj)

    res = prep(data)
    json.dump(res, out, indent=indent)


json_dump(data, sys.stdout, indent=2)

which gives:

{
  "a": 1,
  "b": 2,
  "c": "2022-05-01",
  "d_e": [
    42,
    196
  ],
  "f-g_18-y": "x"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文