2012-11-06 16 views
4

我的目標是在Haskell中編寫一個程序,該程序採用json文件的名稱並將其餘參數解釋爲通過導航該json文件的路徑並打印導航的值至。問題是因爲JSON可以包含多個值類型,我不知道如何讓Haskell的類型系統明白我想要的。下面是「導航」功能,我不能夠正確執行Haskell代碼:在Haskell中以通用方式瀏覽JSON對象

import qualified Data.Aeson as A 
import qualified Data.ByteString.Char8 as BS 
import qualified Data.ByteString.Lazy.Char8 as BSL 
import Data.List 
import Data.Maybe 
import System.Environment 

parse :: String -> A.Value 
parse = fromJust . A.decode . BSL.pack 

isInteger xs = case reads xs :: [(Integer, String)] of 
    [(_, "")] -> True 
    _ -> False 

navigate :: A.Value -> String -> String 
navigate value [] = value 
navigate value [x:xs] 
    | isInteger x = ??? -- value is an array, get the xth element of it. 
    | otherwise = ??? -- value is an map, x is a key in it. 

main :: IO() 
main = do 
    [filename:path] <- getArgs 
    contents <- readFile filename 
    let d = parse contents 
    putStrLn (show (navigate d path)) 

供參考,在這裏是如何在同一個程序會被用Python寫的:

from json import load 
from sys import argv  
def navigate(obj, path): 
    if not path: 
     return obj 
    head, tail = path[0], path[1:] 
    return navigate(obj[int(head) if head.isdigit() else head], tail)  
if __name__ == '__main__': 
    fname, path = argv[1], argv[2:] 
    obj = load(open(fname)) 
    print navigate(obj, path) 

該程序將運行這樣的:

$ cat data.json 
{"foo" : [[1, 2, 3, {"bar" : "barf"}]]} 
$ python showjson.py data.json foo 0 3 bar 
barf 
+0

使用JSON解析解析每個參數,然後編寫一個函數,該函數使用另一個JSON值將其索引爲JSON值,然後結合Python在Python中執行的操作。 – augustss

+0

請注意,當模式匹配使用cons單元格('x:xs')時,您必須使用'(x:xs)'(括號僅用於分組,而不是特殊語法)。 '[x:xs]'與包含單個列表的列表匹配,其中'x'將頭部和'xs'作爲內部列表的尾部。 '[[1,2,3]]'=>'x = 1,xs = [2,3]'。 – huon

+0

感謝您的信息! –

回答

3

你可以爲了弄清楚什麼樣的你正在處理W¯¯JSON對象上的A.Value的構造簡單的模式匹配第i:

import qualified Data.HashMap.Strict as M 
import qualified Data.Vector as V 
import qualified Data.Text as T 

-- ... rest of the code more or less as before ... 

navigate :: A.Value -> [String] -> BSL.ByteString 
navigate value  []  = A.encode value 
navigate (A.Array vs) (x : xs) = navigate (vs V.! read x) xs 
navigate (A.Object o) (x : xs) = navigate (o M.! T.pack x) xs 

注意的A.Value定義如下:

data Value 
    = Object !(HashMap Text Value) 
    | Array !(Vector Value) 
    | ... -- other constructors 

navigate的代碼從而在向量和散列映射,利用該查找功能(在這兩種情況下稱爲!)的。如果需要,函數read用於將命令行參數解釋爲數字(如果不是,則會失敗),而T.pack則將該字符串重新解釋爲Text類型的值。