[英]Aeson: how do I parse an object with an element that is a stringified object?
I need to parse an object that has a string element where the string itself is a stringified object: 我需要解析一个具有字符串元素的对象,其中字符串本身是一个字符串化的对象:
{
"a" : "apples",
"bar" : "{\"b\":\"bananas\"}"
}
I would like to parse this into Just ( Foo { fooA = "apples", fooBar = Bar { barB = "bananas" } } )
so if parsing of bar
returns Nothing
then the parsing of the whole object returns Nothing
, ie the result is as though the bar
element of the object was not stringified. 我想把它解析成
Just ( Foo { fooA = "apples", fooBar = Bar { barB = "bananas" } } )
所以如果bar
的解析返回Nothing
那么解析整个对象会返回Nothing
,即结果是好像对象的bar
元素没有字符串化。
Here is my attempt in which the parsing of testData
returns Nothing
: 这是我尝试解析
testData
返回Nothing
:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Aeson
import Data.Aeson.Types
data Foo = Foo { fooA :: String
, fooBar :: Bar
} deriving (Show)
instance FromJSON Foo where
parseJSON (Object o) = do bar <- (o .: "bar")
Foo <$> o .: "a" <*> parseJSON bar
parseJSON x = typeMismatch "Foo" x
data Bar = Bar { barB :: String
} deriving (Show)
instance FromJSON Bar where
parseJSON (Object o) = Bar <$> o .: "b"
parseJSON x = typeMismatch "Bar" x
testData = "{ \"a\":\"apples\", \"bar\":\"{\\\"b\\\":\\\"bananas\\\"}\" }"
main :: IO ()
main = putStrLn $ show d
where d :: Maybe Foo
d = decode testData
How can I modify the above code to perform closer to what I need? 如何修改上面的代码以更接近我的需要?
You can get more insight into what's going on by using: 您可以通过以下方式更深入地了解正在发生的事情:
main = print (eitherDecode testData :: Either String Foo)
which displays: Left "Error in $: expected Bar, encountered String"
显示:
Left "Error in $: expected Bar, encountered String"
In this code: 在这段代码中:
parseJSON (Object o) = do bar <- (o .: "bar")
Foo <$> o .: "a" <*> parseJSON bar
bar
is String ...
value. bar
是String ...
value。
To accomplish what you want to do, you could add a case to the FromJSON instance for Bar to catch this: 要完成您想要执行的操作,您可以向Bar的FromJSON实例添加一个案例来捕获它:
instance FromJSON Bar where
...
parseJSON (String text) =
case eitherDecode (textToLBS text) of
Left e -> fail $ "while decoding a Bar: " ++ e
Right b -> return b
...
Or you could put this code in the parseJSON definition for Foo. 或者您可以将此代码放在Foo的parseJSON定义中。
Here textToLBS
converts strict Text to lazy ByteStrings: 这里
textToLBS
将严格的Text转换为lazy ByteStrings:
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text.Encoding as TE
textToLBS :: T.Text -> LBS.ByteString
textToLBS t = LBS.fromStrict (TE.encodeUtf8 t)
Code available at: http://lpaste.net/143183 代码见: http : //lpaste.net/143183
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.