【问题标题】:Arbitrary JSON keys with Aeson - Haskell带有 Aeson 的任意 JSON 键 - Haskell
【发布时间】:2013-06-24 14:51:28
【问题描述】:

我有一堆带有任意键的嵌套 JSON 对象。

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

        }
    }

}

ABC 的位置提前未知。这三个中的每一个也可以 有兄弟姐妹。

我想知道是否有办法将其解析为带有 Aeson 的自定义类型 一些优雅的方式。我一直在做的是将它加载到 Aeson Object

您将如何为这种 JSON 实现 FromJSON 对象?

谢谢!

编辑

{
    "USA": {
        "California": {
            "San Francisco": "Some text"
        }
    },
    "Canada": {
        ...
    }
}

这应该编译成CountryDatabase where...

type City            = Map String String
type Country         = Map String City
type CountryDatabase = Map String Country 

【问题讨论】:

  • 不清楚如何你想解析这个 JSON。它总是只有3个嵌套键然后是字符串吗?
  • 你能举一个你想解析成的自定义类型的例子吗?我认为这可以澄清问题。
  • 用更具体的数据结构示例更新了问题。

标签: json haskell aeson


【解决方案1】:

您可以重复使用Map String vFromJSON 实例。类似下一个:

{-# 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)

输出:

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:不用newtypes 也可以,我只是为了清楚起见才使用它们。

【讨论】:

  • 这个答案很有帮助!这可以修改为忽略非字符串值吗? (例如,将"1111" 替换为1111 会导致解析失败。)
  • ToJSON 实例会是什么样子?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多