json在haskell中解析 [英] json parsing in haskell

查看:192
本文介绍了json在haskell中解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图解析haskell中的JSON数据。经过了大量的网站,这是我所能达到的最远。

  data地址=地址{house :: Integer,street :: String,city :: String,state :: String,zip :: Integer}派生(显示)
数据Person = Person {name :: String,age :: Integer,address ::地址}派生(显示)

getName :: Person - > String
getName(Person n _ _)= n

getAddress :: Person - >地址
getAddress(Person _ _ a)= a

getState :: Address - > String
getState(Address _ _ _ s _)= s

文件ex.hs并加载到ghci - >

  Prelude>导入Text.JSON 
前奏Text.JSON> :加载前
主文本.JSON>让aa ={\name \:\some body \,\age \:23,\add​​ress \:{\house \:285 ,街道:第七大道,城市,纽约,国家,纽约 \\,zip \:10001}}
...>解码aa ::结果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,JSString(JSONString {fromJSString =New York})),(zip,JSRational False(10001%1))不用说,它看起来很啰嗦(而且很可怕)。)。))))]]))

我尝试了

  ...>解码aa :: Result Person 

它给我一个错误。我如何去从这个json字符串填充Person数据结构的实例?例如,我该如何获取JSON字符串中的人的状态......

Text.JSON 不知道如何将 JSON 数据转换为
您的 Person 数据类型。为此,您需要使 Person
实例 JSON typeclass,或者您的罐头使用 Text.JSON.Generic
DeriveDataTypeable 扩展名为您完成工作。



泛型



Text.JSON.Generic 方法将读取基于数据类型
结构的 JSON 结构

  { - #LANGUAGE DeriveDataTypeable# - } 
import Text.JSON.Generic

data Address = Address
{house :: Integer
,street ::字符串
,city :: String
,state :: String $ b $,zip :: Integer
}派生(显示,数据,类型化)

数据Person = Person
{name :: String
,age :: Integer
,address :: Address
}派生(Show,Data,Typeable)

aa :: String
aa ={\name \:\some body \,\age \: 23,\地址\:{\house \:285,\street \:\7th Ave. \,\city \:\纽约州\,\state \:\New York \,\zip\:10001}}

main = print(decodeJSON aa: :Person)

只要您不介意将将数据结构中的
字段添加到 JSON 格式中。 另外,您不要需要编写像 getName getAddress
getState 。您记录类型中字段的名称是accesor
函数。

 ∀x。 x⊦:t house 
house ::地址 - >整数
∀x。 x⊦:t地址
地址::人物 - >地址



JSON实例



或者,您可以走高路,并实现自己的
实例 JSON class。

  import Control.Applicative 
import Control.Monad
import Text.JSON

data Address = Address
{house :: Integer
,street :: String
,city :: String
,state :: String
- 重命名以免与Prelude中的zip冲突
,zipC :: Integer
}派生(显示)

数据Person = Person
{name :: String
,age :: Integer
,address :: Address
)派生(显示)

aa :: String
aa ={\name \:\some body \,\age \ :23,\address \:{\house \:285,\street \:\7th Ave. \,\city \:\ 纽约,国家 :\New York \,\zip\:10001}}

- 为了方便
(!)::(JSON a)= > JSObject JSValue - >字符串 - >结果a
(!)=翻转valFromObj

实例JSON地址其中
- 保持编译器安静
showJSON = undefined

readJSON (JSObject obj)=
地址< $>
obj! 房子< *>
obj! 街道< *>
obj! 城市< *>
obj! 状态* *
obj! zip
readJSON _ = mzero

实例JSON Person其中
- 保持编译器安静
showJSON = undefined

readJSON( JSObject obj)=
Person< $>
obj! 名称< *>
obj! 年龄< *>
obj! address
readJSON _ = mzero

main = print(decode aa :: Result Person)

这充分利用了 Result 类型轻松实现 Applicative 的优势
链接在 JSObject 值上的查询。



这是一个稍微多一点的工作,但它给了如果您必须处理会导致样式的 JSON ,那么您可以更多地控制
结构 JSON 准则
由于奇怪的字段名称而被违规。


I'm trying to parse JSON data in haskell. Having gone through a slew of websites, this is the furthest I have been able to get to.

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

I write that in a file ex.hs and load it in 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

It returns

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",JSString (JSONString {fromJSString = "New York"})),("zip",JSRational False (10001 % 1))]}))]}))

Needless to say, it seems pretty verbose (and frightening). I tried doing

...> decode aa :: Result Person

and it gave me an error. How do I go about populating an instance of the Person datastructure from this json string? For example, what should I do to get the state of the person in the JSON string...

解决方案

The problem is that Text.JSON does not know how to convert JSON data to your Person data type. To do this, you need to either make Person and instance of the JSON typeclass, or your can use Text.JSON.Generic and the DeriveDataTypeable extension to do the work for you.

Generics

The Text.JSON.Generic method will read the JSON structure based on the structure of your data type.

{-# LANGUAGE DeriveDataTypeable #-}
import           Text.JSON.Generic

data Address = Address
    { house  :: Integer
    , street :: String
    , city   :: String
    , state  :: String
    , zip    :: Integer
    } deriving (Show, Data, Typeable)

data Person = Person
    { name    :: String
    , age     :: Integer
    , address :: Address
    } deriving (Show, Data, Typeable)

aa :: String
aa = "{\"name\": \"some body\", \"age\" : 23, \"address\" : {\"house\" : 285, \"street\" : \"7th Ave.\", \"city\" : \"New York\", \"state\" : \"New York\", \"zip\" : 10001}}"

main = print (decodeJSON aa :: Person)

This method works really well as long as you don't mind matching the names of the fields in your data structure to your JSON format.

As an aside, you don't need to write functions like getName, getAddress, and getState. The names of the field in your record type are accesor functions.

∀ x. x ⊦ :t house
house :: Address -> Integer
∀ x. x ⊦ :t address
address :: Person -> Address

JSON Instance

Alternatively, you could take the high road and implement your own instance of the JSON class.

import           Control.Applicative
import           Control.Monad
import           Text.JSON

data Address = Address
    { house  :: Integer
    , street :: String
    , city   :: String
    , state  :: String
    -- Renamed so as not to conflict with zip from Prelude
    , zipC   :: Integer
    } deriving (Show)

data Person = Person
    { name    :: String
    , age     :: Integer
    , address :: Address
    } deriving (Show)

aa :: String
aa = "{\"name\": \"some body\", \"age\" : 23, \"address\" : {\"house\" : 285, \"street\" : \"7th Ave.\", \"city\" : \"New York\", \"state\" : \"New York\", \"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)

This takes advantage of the fact that the Result type is an Applicative to easily chain together queries on the JSObject value.

This is a little more work, but it gives you more control of the structure of the JSON if you have to deal with JSON that will cause style guideline violations due to weird field names.

这篇关于json在haskell中解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆