本文介绍了与Aeson - Haskell之间的任意JSON密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  {
A:{
B:{
C:hello

}
}

}

其中 A B C 提前未知。这三者中的每一个都可能还有
有兄弟姐妹。



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



你将如何执行 FromJSON 用于这种JSON
对象?



谢谢!



编辑

  {
USA:{
California:{
旧金山:一些文本
}
},
加拿大:{
...
}
}

这应该编译为 CountryDatabase 其中...

 类型City =地图字符串字符串
类型国家=地图字符串城市
type CountryDatabase = Map String Country


解决方案

FromJSON 地图字符串v 的实例。类似于下一个:

  { - #LANGUAGE OverloadedStrings# - } 

import Data.Functor
导入Data.Monoid
导入Data.Aeson
导入Data.Map(映射)
将限定的Data.ByteString.Lazy导入为LBS
导入System.Environment

newtype City = City(Map String String)
派生Show

instance FromJSON City其中
parseJSON val = City< $> parseJSON val

newtype国家=国家(地图字符串城市)
派生显示
$ b $实例FromJSON国家其中
parseJSON val =国家< $> parseJSON val
$ b $ newtype DB = DB(Map String Country)
派生显示

实例FromJSON DB其中
parseJSON val = DB< $> parseJSON val

main :: IO()
main = do
file< - head< $> getArgs $ b $ str< - LBS.readFile文件
print(decode str :: Maybe DB)

输出:

  shum @ shum-lt:/ tmp / shum $ cat in.js 
{
A:{
A1:{
A11:1111,
A22:2222
}
$ bB:{
}
}
shum @ shum-lt:/ tmp / shum $ runhaskell test.hs in.js
Just (来自List [(A,Country(fromList [(A1,City(fromList [(A11,1111),(A22,2222)]))])),( B,Country(fromList []))]))
shum @ shum-lt:/ tmp / shum

PS:您可以在不使用 newtype s的情况下执行此操作,我只是为了清晰起见才使用它们。


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 alsohave siblings.

I'm wondering if there is a way to parse this into a custom type with Aeson insome 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 JSONobject?

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.

这篇关于与Aeson - Haskell之间的任意JSON密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 08:22