多态类型的 aeson ToJSON 实例

aeson ToJSON instances for polymorphic type

如何为像这样的多态类型手动编写 aeson ToJSON 实例:

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'’

我做错了什么?

编辑:

我将 Translatable 更改为一种类型

type Translatable a = Map.Map String a

现在无需将 Translatable 作为实例添加到 ToJSON 即可工作

但最初的问题仍然是问题

您正在混合使用 toJSONtoEncoding 函数。只需实现 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 ]

我们在 json 个对象的列表上使用 toJSON 函数来创建一个 json 数组。 T.pack key 是必需的,因为您的地图键是 String,但是 .= 需要 Text