使用Aeson时如何在地图中使用求和类型作为键?

时间:2019-06-15 09:42:59

标签: haskell aeson

我想用JSON编码一个简单的“地图”:

{ "CS": "Ahoj"
, "EN": "Hello"
}

我的尝试

{-# LANGUAGE TemplateHaskell, DeriveGeneric, DeriveAnyClass #-}

import Data.Aeson
import Data.Aeson.TH (deriveJSON)
import Data.Text (Text)
import qualified Data.HashMap.Lazy as M
import GHC.Generics (Generic)
import Data.Hashable (Hashable)

data Language
  = CS
  | EN
  deriving (Eq, Show, Generic, Hashable)

deriveJSON defaultOptions ''Language

newtype TranslatedText =
  TranslatedText (M.HashMap Language Text)
  deriving (Eq, Show, Generic)

deriveJSON defaultOptions ''TranslatedText

我得到:

/xxx/src/Data.hs:80:1: error:
    • No instance for (FromJSONKey Language)
        arising from a use of ‘parseJSON’
    • In the second argument of ‘(<$>)’, namely ‘parseJSON arg_apgG’
      In the expression: (TranslatedText <$> parseJSON arg_apgG)
      In a case alternative:
          arg_apgG -> (TranslatedText <$> parseJSON arg_apgG)
   |
80 | deriveJSON defaultOptions ''TranslatedText
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/xxx/src/Data.hs:80:1: error:
    • No instance for (ToJSONKey Language)
        arising from a use of ‘toJSON’
    • In the expression: toJSON arg1_apfY
      In a case alternative: TranslatedText arg1_apfY -> toJSON arg1_apfY
      In the expression:
        case value_apdm of { TranslatedText arg1_apfY -> toJSON arg1_apfY }
   |
80 | deriveJSON defaultOptions ''TranslatedText
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/xxx/src/Data.hs:80:1: error:
    • No instance for (ToJSONKey Language)
        arising from a use of ‘toEncoding’
    • In the expression: toEncoding arg1_apgk
      In a case alternative:
          TranslatedText arg1_apgk -> toEncoding arg1_apgk
      In the expression:
        case value_apg9 of {
          TranslatedText arg1_apgk -> toEncoding arg1_apgk }
   |
80 | deriveJSON defaultOptions ''TranslatedText
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我尝试使用FromJSONKeyToJSONKey编写readMaybeshow实例,但是我不知道应该如何构造一个Parser?还是有一些更好,更自动化的方法?毕竟,总和类型可以轻松地从Text转换为。

1 个答案:

答案 0 :(得分:1)

使用ShowRead({{1}的派生子句需要添加到Read中)是典型实例的样子:

Language

应该有一个更短的方法,我已经提交了一个添加通用实现的提案:https://github.com/bos/aeson/issues/710