Reputation: 25
I have a json like:
{
"name" : "Sam",
"items": [ "sword", "shield", [] ]
}
and a data type
data Adventurer = Adventurer {
name :: String,
items :: [String]
} deriving (Generic, Show, FromJSON, ToJSON)
The problem is caused by the fact that the "items" field has the extra [] in the array and I get "expected String, encountered Array".
I've been trying to fix this with custom data types for the elements of the "items" array, or trying make a custom parser to ignore the extra array.
Is there a way to parse an array and only take the items which are of a certain type, dropping the rest?
Upvotes: 2
Views: 315
Reputation: 476503
Yes, we can for example first construct a function that maps Value
s (these are JSON objects) to Maybe String
s:
import Data.Aeson(Value(String))
import Data.Text(unpack)
getString :: Value -> Maybe String
getString (String t) = Just (unpack t)
getString _ = Nothing
We can then define a custom implementation of FromJOSN
for Adventurer
like:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson(FromJSON(parseJSON), withObject, (.:))
import Data.Maybe(catMaybes)
instance FromJSON Adventurer where
parseJSON = withObject "Adventurer" $ \v -> Adventurer
<$> v .: "name"
<*> fmap (catMaybes . map getString) (v .: "items")
This then yields for example:
Main> t = "{\n \"name\" : \"Sam\",\n \"items\": [ \"sword\", \"shield\", [] ]\n}"
Main> decode t :: Maybe Adventurer
Just (Adventurer {name = "Sam", items = ["sword","shield"]})
Upvotes: 2