В конце концов, как вы кодируете из значения, не приводя к научной нотации?

Я проанализировал большое количество 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]"

Как я могу записать свое значение с числами в более широко приемлемом формате, который могут использовать другие языки? Давайте притворимся, что меня не беспокоят потери точности или целочисленные переполнения. В научном пакете есть средства для форматирования чисел таким образом, но Эсон просто не использовал его.

>formatScientific Fixed Nothing (0.01)
"0.01"

>formatScientific Fixed Nothing (1000000000.1)
"1000000000.1"

person David McHealy    schedule 07.09.2016    source источник
comment
Если другие языки не могут его использовать, это проблема с их парсером JSON. Научное представление является частью стандарта JSON.   -  person Cirdec    schedule 07.09.2016
comment
Принято к сведению. Я все еще хотел бы знать, есть ли способ сделать это без написания моей собственной функции кодирования.   -  person David McHealy    schedule 07.09.2016


Ответы (2)


красивый принтер для 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, который дает вам полный контроль над тем, как должны отображаться числа.

person leftaroundabout    schedule 07.09.2016
comment
Я должен быть в состоянии извлечь хотя бы минимальный код из библиотеки. Если никто не предложит лучший метод, я отмечу его ответом. - person David McHealy; 07.09.2016

Я искал эту функциональность раньше себя; Я полагаю, что в то время я пытался взаимодействовать с программой Ruby, а стандартный парсер Ruby JSON не поддерживал экспоненциальную запись. К сожалению, я считаю, что у aeson нет способа сделать это, поэтому вам нужно будет либо пропатчить aeson, либо написать свой собственный кодировщик.

Дополнительную информацию можно найти в системе отслеживания проблем aeson. Эта проблема дополнительно предлагает использовать toEncoding для типа, отличного от Value, чтобы добиться этого, но неясно, практично ли это в вашем случае или нет.

person Daniel Wagner    schedule 07.09.2016