I have the following code:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Tree
main :: IO ()
main = print $ decode "[1,[2,[]]]" :: Maybe (Tree Int)
But the output is "Nothing" in the console. How can I parse JSON data into Tree String
, Tree Int
types ? As far as I know, Tree v
has a fromJSON
instance as long as v
has a fromJSON
instance.
CodePudding user response:
I’m not very familiar with how Aeson defines these instances, so I went looking on Hackage. In the module where this instance is defined, Data.Aeson.Types.ToJSON
, I see this code:
instance ToJSON1 Tree.Tree where
liftToJSON t tol = go
where
go (Tree.Node root branches) =
liftToJSON2 t tol to' tol' (root, branches)
to' = liftToJSON go (listValue go)
tol' = liftToJSONList go (listValue go)
liftToEncoding t tol = go
where
go (Tree.Node root branches) =
liftToEncoding2 t tol to' tol' (root, branches)
to' = liftToEncoding go (listEncoding go)
tol' = liftToEncodingList go (listEncoding go)
instance (ToJSON v) => ToJSON (Tree.Tree v) where
toJSON = toJSON1
toEncoding = toEncoding1
The call to liftToJSON2
here, and reading instance ToJSON2 (,)
and instance ToJSON1 []
, tells me that a Node
is represented as an array of two elements, where the former is the encoding of the root value, and the latter is the encoding of the branches. Since this is a list, it’s also encoded as an array.
So your example case [1,[2,[]]]
is close, but you’re missing one level of nesting—since Tree 1 [Tree 2 []]
is encoded via (1, [(2, [])])
, I infer that it needs to be [1,[[2,[]]]]
. This is probably documented somewhere, but I can’t easily find it.