Aeson:将一个JSON对象转换为一个List of key, value类型

Aeson: converting a JSON object to a List of key, value type

我有一些 JSON 字段存储在数据库中,其中包含 String -> Double 映射,例如:

{
  "some type of thing": 0.45,
  "other type of thing": 0.35,
  "something else": 0.2
}

我想将其表示为 ThingComposition:

data ThingType = ThingTypeSome
               | ThingTypeOther
               | ThingTypeUnknown Text

-- | Create a ThingType from a text representation
txtToThing :: Text -> ThingType
txtToThing "some type of thing"  = ThingTypeSome
txtToThing "other type of thing" = ThingTypeOther
txtToThing s                     = ThingTypeUnknown s

-- Deserialise ThingType from JSON text
instance FromJSON ThingType where
  parseJSON val = withText "ThingType" (return . txtToThing) val

data ThingComposition = ThingComposition [(ThingType, Double)]
                      | InvalidThingComposition

instance FromJSON ThingComposition where
  parseJSON val = withObject "ThingComposition"
                             _
                             val

_是我不知道怎么填的。我尝试了类似下面的方法,但我无法让类型对齐,而且我无法找到最好的方法,因为 JSON 表示可能与类型不匹配,但我不想创建 [(Either String ThingType, Either String Double)] 的列表。如何将顶部的对象解析为 ThingComposition 类型?

_ = (return . ThingComposition) . map (bimap parseJSON parseJSON) . toList

我会为您的 ThingType 制作一些支持实例,然后重新使用 FromJSON (HashMap k v) 实例。

-- added "deriving Eq" to your declaration; otherwise unchanged
data ThingType = ThingTypeSome
               | ThingTypeOther
               | ThingTypeUnknown Text
               deriving Eq

thingToTxt :: ThingType -> Text
thingToTxt ThingTypeSome = "some type of thing"
thingToTxt ThingTypeOther = "other type of thing"
thingToTxt (ThingTypeUnknown s) = s

instance FromJSONKey ThingType where
    fromJSONKey = FromJSONKeyText txtToThing
instance Hashable ThingType where
    hashWithSalt n = hashWithSalt n . thingToTxt

有了支持代码,您现在就有了 HashMap ThingType DoubleFromJSON 实例,它在很多方面都优于 [(ThingType, Double)]