Vector pattern matching value in Data.Aeson

I am using Data.Aseon to parse JSON for my custom type. I am trying to match match Vector Value( Array) on an instance FromJSON, but don't know how I can do this. JSON valuecan have a value String, a list, Stringor a list from a list String.

instance FromJSON Foo where
  parseJSON (Object o) =
    case lookup "value" o of
      Just (String s) -> pure $ SimpleText s
      Just foo@(Array (String s)) -> pure $ ListOfText $ V.toList <$> V.mapM (parseJSON :: Value -> Parser Text) foo
      Just foo@(Array (Array (String s))) -> pure $ ListOfListOfText $ V.toList <$> V.mapM (parseJSON :: Value -> Parser Text) $ V.toList <$> V.mapM (parseJSON :: Value -> [Parser Value]) foo

with

data Foo = SimpleText Text
         | ListOfText [Text]
         | ListOfListOfText [[Text]]
         deriving (Show, Eq, Ord)

Can I use pattern matching in Array to handle this case? or should I manually check each type value? and how to handle it?

+4
source share
1 answer

, , . JSON , , , .

. , , .

, FromJSON Text [a]. - Alternative :

instance FromJSON Foo where
    parseJSON v =  (SimpleText <$> parseJSON v) 
               <|> (ListOfText <$> parseJSON v) 
               <|> (ListOfListOfText <$> parseJSON v)

, Aeson Text, , , [Text], , [[Text]].

, , JSON , . , Null , , [[Text]], .

, , . , , ListOfText ListOfListOfText? Vector , :

instance FromJSON Foo where
    parseJSON v = case v of
        -- If its a string, we return the string as a SimpleText
        (String s) -> return $ SimpleText s

        -- If its an array, we turn the vector to a list so we can pattern match on it
        (Array a)  -> case V.toList a of

            -- If its a empty list, we return a empty ListOfText
            []             -> return $ ListOfText []

            -- If the first value is a string, we put it as the first element of our ListOfTexts and try to parse the rest.
            (String s: xs) -> ListOfText . (s:) <$> mapM parseJSON xs

            -- If the first value is an array, we try to parse it as [Text], then parse the rest.
            (Array a: xa)  -> ListOfListOfText <$> ((:) <$> parseJSON (Array a) <*> mapM parseJSON xa)

            -- If the first value is neither a string or array we return a error message.
            _              -> fail "Expected an Array or an Array of Arrays."

        -- If the top level value is not a string or array we return a error message.
        _ -> fail "Expected a String or Array"
+3

All Articles