When I load a number with e form a JSON dump with YAML, the number is loaded as a string and not a float.

我想这个简单的例子可以解释我的问题.

import json
import yaml

In [1]: import json

In [2]: import yaml

In [3]: All = {'one':1,'low':0.000001}

In [4]: jAll = json.dumps(All)

In [5]: yAll = yaml.safe_load(jAll)

In [6]: yAll
Out[6]: {'low': '1e-06', 'one': 1}

YAML将1e-06作为字符串而不是数字加载?我怎么才能把它修好呢?

推荐答案

The problem lies in the fact that the YAML Resolver is set up to match floats as follows:

Resolver.add_implicit_resolver(
    u'tag:yaml.org,2002:float',
    re.compile(u'''^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?
    |\\.[0-9_]+(?:[eE][-+][0-9]+)?
    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*
    |[-+]?\\.(?:inf|Inf|INF)
    |\\.(?:nan|NaN|NAN))$''', re.X),
    list(u'-+0123456789.'))

whereas the YAML spec specifies the regex for scientific notation as:

-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?

后者使点成为可选的,在隐式解析器中,它不在上述re.compile()个模式中.

The matching of floats can be fixed so it will accept floating point values with an e/E but without decimal dot and with exponents without sign (i.e. + implied):

import yaml
import json
import re

All = {'one':1,'low':0.000001}

jAll = json.dumps(All)

loader = yaml.SafeLoader
loader.add_implicit_resolver(
    u'tag:yaml.org,2002:float',
    re.compile(u'''^(?:
     [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)?
    |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+)
    |\\.[0-9_]+(?:[eE][-+][0-9]+)?
    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*
    |[-+]?\\.(?:inf|Inf|INF)
    |\\.(?:nan|NaN|NAN))$''', re.X),
    list(u'-+0123456789.'))

data = yaml.load(jAll, Loader=loader)
print 'data', data

results in:

data {'low': 1e-06, 'one': 1}

JSON允许的数字和YAML 1.2规范中的正则表达式之间存在差异(关于数字中所需的点,e是小写).

在此处输入图像描述

The PyYAML implementation does match floats partially according to the JSON spec and partially against the regex and fails on numbers that should be valid.

ruamel.yaml(这是我的PyYAML的增强版本),有这些更新的模式,并且工作正常:

import ruamel.yaml
import json

All = {'one':1,'low':0.000001}

jAll = json.dumps(All)

data = ruamel.yaml.load(jAll)
print 'data', data

with output:

data {'low': 1e-06, 'one': 1}

鲁阿迈尔.yaml还接受数字"1.0e6",PyYAML也将其视为字符串.

Json相关问答推荐

合并二维数组的Jolt表达式

如何形成正确的JQ表达式以从JSON文件中获得准确的输出数据?

如何在对象投影(*)上应用滤镜投影([?port==`eth1`])?

如何使用GoFr返回XML响应?

JQ:获取该值的较短语法是什么

如何在Android中解析带有动态键和可变对象名称的改装JSON响应?

展平多个数组以保持顺序

Powershell解析JSON文件中的键或值

使用 json_query 过滤嵌套列表中的元素

如何使用 ConfigurationBuilder 解析现有的 json 字符串(不是文件)

Json.NET SerializeObject 转义值以防止 XSS

错误字符串的长度超过了maxJsonLength属性设置的值

如何一次加载无限滚动中的所有条目以解析python中的HTML

json.dumps 打乱了顺序

如何使用 LWP 发出 JSON POST 请求?

JSON 到 JSON 转换器

Peewee 模型转 JSON

Python 到 JSON 序列化在十进制上失败

通过 JSON 发送 64 位值的公认方式是什么?

如何对 jq 中的 map 数组中的值求和?