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

Time:09-17

I have some JSON fields stored in a database which contain a String -> Double mapping, e.g.:

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

I want to represent this as a 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

The _ is what I have no idea how to fill out. I've tried something like the following but I can't get the types to align and I can't work out the best way to do this, given that it's possible that the JSON representation won't match the types, but I don't want to create a list of [(Either String ThingType, Either String Double)]. How can I parse that the object at the top into the ThingComposition type?

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

CodePudding user response:

I would make some supporting instances for your ThingType, then reuse the FromJSON (HashMap k v) instance.

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

With that supporting code, you now have a FromJSON instance for HashMap ThingType Double, which is superior in many ways to a [(ThingType, Double)].

  • Related