aeson To JSON экземпляры для типа polymorphi c - PullRequest
0 голосов
/ 15 апреля 2020

Как записать эсон в JSON экземпляров от руки для полиморфа типа c, например:

data Show a => Translatable a = Translatable (Map.Map String a)
    deriving (Show, Eq, Typeable)

Я хотел бы закодировать

Translatable $ Map.fromList [("key", "value"), ("key2", "value2")]

в json объект типа { "key", "value", "key2", "value2" }

То, что я до сих пор пробовал, это:

import qualified Data.Aeson as A
import Data.Data (Typeable)
import qualified Data.Map as Map

data Show a => Translatable a = Translatable (Map.Map String a)
    deriving (Show, Eq, Typeable)

instance Show a => A.ToJSON (Translatable a) where
    toEncoding xs = A.object $ map (.=) (Map.toList xs)

Ошибка

 Couldn't match type ‘A.Value’
 with ‘Data.Aeson.Encoding.Internal.Encoding' A.Value’
      Expected type: A.Encoding
        Actual type: A.Value

Документация Aeson показывает: type Encoding = Encoding' Value

Но A.Encoding 'не находится в области действия

Not in scope: data constructor ‘A.Encoding'’

что я делаю не так?

РЕДАКТИРОВАТЬ:

Я изменил свой переводимый на тип

type Translatable a = Map.Map String a

И теперь он работает без добавления Transhable в качестве экземпляра в To JSON

Но первоначальный вопрос по-прежнему остается вопросом.

1 Ответ

1 голос
/ 16 апреля 2020

Вы смешиваете функции toJSON и toEncoding. Просто реализуйте функцию toJSON вашего экземпляра ToJSON. Я импортировал Data.Aeson без квалификации, чтобы меньше бороться с операторами.

import Data.Aeson
import qualified Data.Text as T

--- etc.

instance Show a => ToJSON (Translatable a) where
    toJSON (Translatable myMap) = toJSON
        [ object [ T.pack key .= show val ] | (key, val) <- Map.toList myMap ]

Мы используем функцию toJSON в списке объектов json для создания массива json. T.pack key необходимо, поскольку ваши ключи карты String s, но .= требуется Text.

...