I have a bunch of nested JSON objects with arbitrary keys.
{
    "A": {
        "B": {
            "C": "hello"
        }
    }
}
Where A, B, C are unknown ahead of time.  Each of those three could also
have siblings.
I'm wondering if there is a way to parse this into a custom type with Aeson in
some elegant way.  What I have been doing is loading it into an Aeson Object.
How would you go about implementing the FromJSON for this kind of JSON
object?
Thanks!
Edit:
{
    "USA": {
        "California": {
            "San Francisco": "Some text"
        }
    },
    "Canada": {
        ...
    }
}
This should compile to CountryDatabase where...
type City            = Map String String
type Country         = Map String City
type CountryDatabase = Map String Country 
                You can reuse FromJSON instance of Map String v. Something like the next:
{-# LANGUAGE OverloadedStrings #-}
import Data.Functor
import Data.Monoid
import Data.Aeson
import Data.Map (Map)
import qualified Data.ByteString.Lazy as LBS
import System.Environment
newtype City = City (Map String String)
  deriving Show
instance FromJSON City where
  parseJSON val = City <$> parseJSON val
newtype Country = Country (Map String City)
  deriving Show
instance FromJSON Country where
  parseJSON val = Country <$> parseJSON val
newtype DB = DB (Map String Country)
  deriving Show
instance FromJSON DB where
  parseJSON val = DB <$> parseJSON val
main :: IO ()
main = do
  file <- head <$> getArgs
  str <- LBS.readFile file
  print (decode str :: Maybe DB)
The output:
shum@shum-lt:/tmp/shum$ cat in.js 
{
    "A": {
        "A1": {
            "A11": "1111",
            "A22": "2222"
        }
    },
    "B": {
    }
}
shum@shum-lt:/tmp/shum$ runhaskell test.hs in.js 
Just (DB (fromList [("A",Country (fromList [("A1",City (fromList [("A11","1111"),("A22","2222")]))])),("B",Country (fromList []))]))
shum@shum-lt:/tmp/shum$
PS: You can do it without newtypes, I used them only for clarity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With