Arbitrary JSON keys with Aeson - Haskell

前端 未结 1 501
北恋
北恋 2021-02-08 01:19

I have a bunch of nested JSON objects with arbitrary keys.

{
    \"A\": {
        \"B\": {
            \"C\": \"hello\"

        }
    }

}

Whe

1条回答
  •  失恋的感觉
    2021-02-08 01:56

    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.

    0 讨论(0)
提交回复
热议问题