djh*_*rld 19 parsing json haskell
我很难理解这一点(我对Haskell仍然有点新鲜)但是我发现Text.JSON包的文档有点令人困惑.基本上我有这种数据记录类型: - 
data Tweet = Tweet
    {
        from_user :: String,
        to_user_id :: String,
        profile_image_url :: String,
        created_at :: String,
        id_str :: String,
        source :: String,
        to_user_id_str :: String,
        from_user_id_str :: String,
        from_user_id :: String,
        text :: String,
        metadata :: String
    }
我有一些JSON格式的推文符合这种类型的结构.我正在努力的是如何将上面的内容映射到从以下代码返回的内容
decode tweet :: Result JSValue
进入上面的数据类型.我明白我应该创建一个实例,instance JSON Tweet但我不知道从那里去哪里.
任何指针都将非常感谢,谢谢!
tib*_*bbe 25
我建议您使用新的aeson软件包而不是json软件包,因为前者的性能要好得多.以下是使用aeson将JSON对象转换为Haskell记录的方法:
{-# LANGUAGE OverloadedStrings #-}
module Example where
import Control.Applicative
import Control.Monad
import Data.Aeson
data Tweet = Tweet {
    from_user :: String,
    to_user_id :: String,
    profile_image_url :: String,
    created_at :: String,
    id_str :: String,
    source :: String,
    to_user_id_str :: String,
    from_user_id_str :: String,
    from_user_id :: String,
    text :: String,
    metadata :: String
    }
instance FromJSON Tweet where
    parseJSON (Object v) =
        Tweet <$> v .: "from_user"
              <*> v .: "to_user_id"
              <*> v .: "profile_image_url"
              <*> v .: "created_at"
              <*> v .: "id_str"
              <*> v .: "source"
              <*> v .: "to_user_id_str"
              <*> v .: "from_user_id_str"
              <*> v .: "from_user_id"
              <*> v .: "text"
              <*> v .: "metadata"
    -- A non-Object value is of the wrong type, so use mzero to fail.
    parseJSON _          = mzero
然后使用Data.Aeson.json获取将a转换为a 的attoparsec解析器.该呼叫在试图解析它变成你的记录.请注意,这两个步骤涉及两个不同的解析器,一个用于转换为通用JSON 的解析器,另一个用于将JSON值转换为记录的解析器.请注意,这两个步骤都可能失败ByteStringValuefromJSONValueData.Attoparsec.ParserByteStringValueData.Aeson.Types.Parser
ByteString不是有效的JSON值,则它可能会失败.fromJSON实现中提到的字段之一,则第二个解析器可能会失败.aeson包更喜欢新的Unicode类型Text(在文本包中定义)到更旧的学校String类型.该Text类型具有更高的内存效率表示,String并且通常表现更好.我建议您更改Tweet要使用的类型Text而不是String.
如果您需要在String和之间进行转换Text,请使用中定义的pack和unpack函数Data.Text.请注意,此类转换需要O(n)时间,因此请尽可能避免使用(即始终使用Text).
Don*_*art 14
你需要写一个showJSON和readJSON方法,为你的类型,建立你的Haskell值了JSON格式.JSON包将负责将原始字符串解析为a JSValue.
您的推文JSObject最多可能包含字符串映射.  
show看JSObject,看场的布局方式.get_field上JSObject.fromJSString从中获取常规Haskell字符串JSString.从广义上讲,你需要的东西,
{-# LANGUAGE RecordWildCards #-}
import Text.JSON
import Text.JSON.Types
instance JSON Tweet where
    readJSON (JSObject o) = return $ Tweet { .. }
            where from_user         = grab o "from_user"
                  to_user_id        = grab o "to_user_id"
                  profile_image_url = grab o "proile_image_url"
                  created_at        = grab o "created_at"
                  id_str            = grab o "id_str"
                  source            = grab o "source"
                  to_user_id_str    = grab o "to_user_id_str"
                  from_user_id_str  = grab o "from_user_id_str"
                  from_user_id      = grab o "from_user_id"
                  text              = grab o "text"
                  metadata          = grab o "metadata"
grab o s = case get_field o s of
                Nothing            -> error "Invalid field " ++ show s
                Just (JSString s') -> fromJSString s'
注意,我正在使用相当酷的通配符语言扩展.
如果没有JSON编码的示例,我可以提供更多建议.
有关
您可以通过实例找到JSON编码的示例实例