Mario
Mario

Reputation: 185

How can I parse data for parseJSON?

I have a data which I want to parse from json:

data MyData = MyData 
    { myDataId :: UUID 
    , myDataVar1 :: Bool
    , myDataVar2 :: Maybe (UUID, String)
    }

instance FromJSON MyData where
  parseJSON (Object v) =
    MyData <$> v .: "id"
        <*> v .: "var1"
        <*> ((,) <$> ((v .: "var2") >>= (.: "id")) <*> ((v .: "var2") >>= (.: "name"))) --- ??? doesn't work

How can I parse myDataVar2?

Upvotes: 0

Views: 87

Answers (1)

Random Dev
Random Dev

Reputation: 52280

this based on the suspected JSON @zeta gave and the idea of @dfeuer

here is a compiling/working example

{-# LANGUAGE OverloadedStrings #-}
module ParseJson where

import Data.Aeson
import Data.Text
import Data.Text.Encoding
import Data.ByteString.Lazy (fromStrict)

testData :: Text
testData = "{ \"id\" :\"A211MNLR\", \"var1\": false, \"var2\": { \"id\": \"GA23210X\", \"name\": \"child\"} }"

testData2 :: Text
testData2 = "{ \"id\" :\"GA23210X\", \"var1\": false, \"var2\": null}"

data MyData = MyData 
    { myDataId :: Text
    , myDataVar1 :: Bool
    , myDataVar2 :: Maybe (Text, Text)
    } deriving Show

instance FromJSON MyData where
  parseJSON (Object v) =
    MyData <$> v .: "id"
           <*> v .: "var1"
           <*> (v .:? "var2" >>= parsePair)
    where parsePair (Just (Object o)) = Just <$> ((,) <$> o .: "id" <*> o.: "name")
          parsePair _                 = pure Nothing

parse :: Text -> Maybe MyData
parse = decode . fromStrict . encodeUtf8

here are the tests:

λ> parse testData
Just (MyData {myDataId = "A211MNLR", myDataVar1 = False, myDataVar2 = Just ("GA23210X","child")})
λ> parse testData2
Just (MyData {myDataId = "GA23210X", myDataVar1 = False, myDataVar2 = Nothing})

remarks

  • I used Text instead of UUID - as far as I can see there is a fromText in the uuid package you can use to transform it further (but it's a Maybe UUID as well) or you could write the FromJSON instance for it - sadly I have no time to do it right - sorry :(
  • it's not pretty and there is probably an operator for what I did with parsePair already there

but it should be a start for you to figure it out

Upvotes: 1

Related Questions