Кто-нибудь знает, где я могу найти документацию о том, как ADT переводятся в Json с помощью Aeson ToJSON? Я использую Haskell для внутреннего приложения и пытаюсь написать декодер JSON для другого функционального языка во внешнем интерфейсе, поэтому я хотел бы использовать тот же формат JSON, чтобы я мог отправлять сообщения между ними.
Спецификация формата ToJson по умолчанию, используемого Aeson
Ответы (2)
Я не думаю, что это очень хорошо задокументировано, но я добился большого успеха в подобных ситуациях, используя экземпляр QuickCheck Arbitrary
для создания большого количества исходных типов, кодируя их в JSON, а затем используя их в качестве золотого стандарта. тесты для вашего интерфейса.
Вы также можете получить некоторое представление о том, как работает кодирование Aeson Template Haskell, заглянув по адресу настраиваемый Options
введите Data.Aeson.TH
. В частности, взгляните на SumEncoding
, который позволит мне объяснить, например, что Either
кодируется с использованием ObjectWithSingleField
, то есть {"Left": 3}
вместо Left 3
.
Конечно, просмотр кейсов, сгенерированных QuickCheck, — это своего рода практическое решение.
Но при размышлении удобно иметь некую концептуальную картину возможных вариантов перевода.
Я рассмотрел все доступные варианты перевода типов сумм в aeson
и generic-aeson
в ответе здесь, с Примеры.
Но особенность этого примера в том, что данные являются записями. Что-то может измениться в примерах, если это не так.
Итак, моя концептуальная картина (пожалуй, еще не полная и не совсем правильная) такова:
если тип не является нетривиальной суммой,
- but is like a newtype (or has a single unary data constructor), this is simply a no-op in JSON.
- Если это запись, она становится объектом.
- Если это реальный, нетривиальный тип продукта (а не запись), то .... (наверное, массив).
есть специальные основные случаи:
Maybe a
,[a]
, различныеString
-подобные типы,Bool
,Int
-подобные, ...если тип представляет собой нетривиальную сумму, то важно, является ли он «перечислением» (имеющим все нульарные конструкторы) или нет.
- enums are translated into strings with the values;
- non-enums according to a
SumEncoding
option:- whether it is a record or not may also make a difference (like in the first case of non-sums).
Пожалуйста, поправьте меня или дополните недостающие пункты.