我试图解析
haskell中的
JSON数据.经历了大量的网站,这是我能够达到的最远的.
data Address = Address { house :: Integer,street :: String,city :: String,state :: String,zip :: Integer } deriving (Show) data Person = Person { name :: String,age :: Integer,address :: Address } deriving (Show) getName :: Person -> String getName (Person n _ _) = n getAddress :: Person -> Address getAddress (Person _ _ a) = a getState :: Address -> String getState (Address _ _ _ s _) = s
我在一个文件ex.hs中写,并将其加载到ghci – >
Prelude> import Text.JSON Prelude Text.JSON> :load ex Main Text.JSON> let aa = "{\"name\": \"some body\",\"age\" : 23,\"address\" : {\"house\" : 285,\"street\" : \"7th Ave.\",\"city\" : \"New York\",\"state\" : \"New York\",\"zip\" : 10001}}" ...> decode aa :: Result JSValue
它返回
Ok (JSObject (JSONObject {fromJSObject = [("name",JSString (JSONString {fromJSString = "some body"})),("age",JSRational False (23 % 1)),("address",JSObject (JSONObject {fromJSObject = [("house",JSRational False (285 % 1)),("street",JSString (JSONString {fromJSString = "7th Ave."})),("city",JSString (JSONString {fromJSString = "New York"})),("state",("zip",JSRational False (10001 % 1))]}))]}))
不用说,看起来很冗长(可怕).我试过
...> decode aa :: Result Person
它给了我一个错误.如何从这个json字符串中填充Person数据结构的实例?例如,我应该怎么做才能获得JSON字符串中的人的状态?
解决方法
问题是Text.JSON不知道如何将JSON数据转换为
您的人员数据类型.要做到这一点,你需要做个人和
JSON类型实例,或者可以使用Text.JSON.Generic和
DeriveDataTypeable扩展为你做的工作.
您的人员数据类型.要做到这一点,你需要做个人和
JSON类型实例,或者可以使用Text.JSON.Generic和
DeriveDataTypeable扩展为你做的工作.
泛型
Text.JSON.Generic方法将读取基于JSON的结构
数据类型的结构.
{-# LANGUAGE DeriveDataTypeable #-} import Text.JSON.Generic data Address = Address { house :: Integer,city :: String,state :: String,zip :: Integer } deriving (Show,Data,Typeable) data Person = Person { name :: String,age :: Integer,address :: Address } deriving (Show,Typeable) aa :: String aa = "{\"name\": \"some body\",\"zip\" : 10001}}" main = print (decodeJSON aa :: Person)
只要您不介意匹配字段的名称,此方法的工作效果非常好
在您的数据结构中,您的JSON格式.
除此之外,您不需要编写getName,getAddress,
和getState.您的记录类型中的字段名称是accesor
功能.
∀ x. x ⊦ :t house house :: Address -> Integer ∀ x. x ⊦ :t address address :: Person -> Address
JSON实例
或者,你可以走高路,实现自己的实例
JSON类.
import Control.Applicative import Control.Monad import Text.JSON data Address = Address { house :: Integer,state :: String -- Renamed so as not to conflict with zip from Prelude,zipC :: Integer } deriving (Show) data Person = Person { name :: String,address :: Address } deriving (Show) aa :: String aa = "{\"name\": \"some body\",\"zip\" : 10001}}" -- For convenience (!) :: (JSON a) => JSObject JSValue -> String -> Result a (!) = flip valFromObj instance JSON Address where -- Keep the compiler quiet showJSON = undefined readJSON (JSObject obj) = Address <$> obj ! "house" <*> obj ! "street" <*> obj ! "city" <*> obj ! "state" <*> obj ! "zip" readJSON _ = mzero instance JSON Person where -- Keep the compiler quiet showJSON = undefined readJSON (JSObject obj) = Person <$> obj ! "name" <*> obj ! "age" <*> obj ! "address" readJSON _ = mzero main = print (decode aa :: Result Person)
这样可以很好地利用结果类型是一个很容易应用的事实
链接在一起查询JSObject值.
这是一个更多的工作,但它给你更多的控制的结构JSON,如果你必须处理将导致风格指南的JSON由于奇怪的字段名称而导致违规.