在 aeson 中,如何在不产生科学记数法的情况下从值进行编码?
In aeson, how do you encode from a Value without resulting in scientific notation?
我已经解析了大量 json,操纵了一些值,我想将其写回。 Aeson 将数字解码为科学数字,但当它对其进行编码时,默认情况下,科学在许多情况下以科学计数法显示数字,而 aeson 没有提供任何我可以看到的方式来改变它。
> decode "[\"asdf\", 1, 1.0, 1000000000.1, 0.01]" :: Maybe Value
Just (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
encode (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"
> encode (Array [String "asdf", Number 1, Number 1.0, Number 1000000000.1, Number 0.01])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"
如何以其他语言可以使用的更广泛接受的格式用数字写出我的值?假设我不关心精度损失或整数溢出。 scientific 包有这种格式化数字的方法,aeson 只是碰巧没有使用它。
>formatScientific Fixed Nothing (0.01)
"0.01"
>formatScientific Fixed Nothing (1000000000.1)
"1000000000.1"
我之前已经寻找过这个功能;我相信当时我正在尝试与 Ruby 程序交互,而标准 Ruby JSON 解析器不支持科学记数法。不幸的是,我相信 aeson 没有办法做到这一点,所以你需要给 aeson 打补丁或编写你自己的编码器。
还有更多详细信息on the aeson issue tracker。该问题还建议在 Value
以外的类型上使用 toEncoding
来实现此目的,但目前尚不清楚这对您的情况是否可行。
pretty printer for Aeson(仅从 0.8 版开始,非常新)有一个配置选项可以完全满足您的要求:
Prelude> :m +Data.Aeson Data.Aeson.Encode.Pretty
Prelude Data.Aeson Data.Aeson.Encode.Pretty> encodePretty' (defConfig{confNumFormat=Decimal}) (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1.0,\n 1.0,\n 1000000000.1,\n 0.01\n]"
不幸的是,这个漂亮的打印机现在将实际整数输出为 1.0
而不是 1
,我认为这比用科学记数法打印小数(这实际上应该是到处都可以)。默认设置也会发生这种情况:
Prelude Data.Aeson Data.Aeson.Encode.Pretty> encodePretty (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1.0,\n 1.0,\n 1.0000000001e9,\n 1.0e-2\n]"
版本 0.7.2 仍然打印没有小数部分的整数,就像正常的 aeson encode
一样:
aeson-pretty-0.7.2:Data.Aeson.Encode.Pretty> encodePretty (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1,\n 1,\n 1.0000000001e9,\n 1.0e-2\n]"
我想我会将其作为错误报告归档。
请注意,还有一个 Custom
NumberFormat
选项,可让您完全控制数字的显示方式。
我已经解析了大量 json,操纵了一些值,我想将其写回。 Aeson 将数字解码为科学数字,但当它对其进行编码时,默认情况下,科学在许多情况下以科学计数法显示数字,而 aeson 没有提供任何我可以看到的方式来改变它。
> decode "[\"asdf\", 1, 1.0, 1000000000.1, 0.01]" :: Maybe Value
Just (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
encode (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"
> encode (Array [String "asdf", Number 1, Number 1.0, Number 1000000000.1, Number 0.01])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"
如何以其他语言可以使用的更广泛接受的格式用数字写出我的值?假设我不关心精度损失或整数溢出。 scientific 包有这种格式化数字的方法,aeson 只是碰巧没有使用它。
>formatScientific Fixed Nothing (0.01)
"0.01"
>formatScientific Fixed Nothing (1000000000.1)
"1000000000.1"
我之前已经寻找过这个功能;我相信当时我正在尝试与 Ruby 程序交互,而标准 Ruby JSON 解析器不支持科学记数法。不幸的是,我相信 aeson 没有办法做到这一点,所以你需要给 aeson 打补丁或编写你自己的编码器。
还有更多详细信息on the aeson issue tracker。该问题还建议在 Value
以外的类型上使用 toEncoding
来实现此目的,但目前尚不清楚这对您的情况是否可行。
pretty printer for Aeson(仅从 0.8 版开始,非常新)有一个配置选项可以完全满足您的要求:
Prelude> :m +Data.Aeson Data.Aeson.Encode.Pretty
Prelude Data.Aeson Data.Aeson.Encode.Pretty> encodePretty' (defConfig{confNumFormat=Decimal}) (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1.0,\n 1.0,\n 1000000000.1,\n 0.01\n]"
不幸的是,这个漂亮的打印机现在将实际整数输出为 1.0
而不是 1
,我认为这比用科学记数法打印小数(这实际上应该是到处都可以)。默认设置也会发生这种情况:
Prelude Data.Aeson Data.Aeson.Encode.Pretty> encodePretty (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1.0,\n 1.0,\n 1.0000000001e9,\n 1.0e-2\n]"
版本 0.7.2 仍然打印没有小数部分的整数,就像正常的 aeson encode
一样:
aeson-pretty-0.7.2:Data.Aeson.Encode.Pretty> encodePretty (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\n \"asdf\",\n 1,\n 1,\n 1.0000000001e9,\n 1.0e-2\n]"
我想我会将其作为错误报告归档。
请注意,还有一个 Custom
NumberFormat
选项,可让您完全控制数字的显示方式。