使用 Aeson 解析 JSON 以映射字符串字符串
Parsing JSON to Map String String with Aeson
我正在尝试从 API 中解析 JSON,其数据结构类似于
{
"en": {
"translation": {
"name": "Name",
"description": ["I am a", "en person"]
}
},
"jp": {
"translation": {
"name": "JP Name",
"description": ["I am a", "jp person"]
}
}
}
所以我只想将它们解析为 newtype Translations = Map String String
之类的东西。语言环境将是键名,值将只是 JSON 翻译的字符串,如 {"name": "Name", "description": ["I am a", en person"]}
,因为该值可以任意复杂,我不想 care/need 将其转换为其他 Haskell 数据结构。
我试了很多方法为 Translation
写一个合适的 parseJSON
但还是做不到。
如有任何帮助,我们将不胜感激!
我们可以解码ByteString
:
Prelude Data.Aeson Bs Hm Mp Tx> decode text :: Maybe Object
Just (fromList [("jp",Object (fromList [("translation",Object (fromList [("name",String "JP Name"),("description",Array [String "I am a",String "jp person"])]))])),("en",Object (fromList [("translation",Object (fromList [("name",String "Name"),("description",Array [String "I am a",String "en person"])]))]))])
那么我们只需要对包裹在`Object构造函数中的HashMap Text Object
进行映射:
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as Bs
import qualified Data.HashMap.Lazy as Hm
import qualified Data.Map as Mp
import qualified Data.Text as Tx
process :: Value -> Maybe (Mp.Map String String)
process (Object m) = Just ((Mp.fromList . map f) (Hm.toList m))
where f (x, y) = (Tx.unpack x, Bs.unpack (encode y))
process _ = Nothing
然后我们得到一个包裹在Maybe
中的Map String String
(因为两者都解码,并且处理可能出错,所以使用Maybe
可能更好),即映射String
s 在 String
s:
Prelude Data.Aeson Bs Hm Mp Tx> decode text >>= process
Just (fromList [("en","{\"translation\":{\"name\":\"Name\",\"description\":[\"I am a\",\"en person\"]}}"),("jp","{\"translation\":{\"name\":\"JP Name\",\"description\":[\"I am a\",\"jp person\"]}}")])
也就是说,我不确定 JSON 作为值的 blob 是否是您想要的,因为现在不能 "look into" 该值并检查该元素中的内容。此外,如果您想进行大量查找,当您想检查两个 Text
是否相同时,Text
通常会快一个数量级。
我正在尝试从 API 中解析 JSON,其数据结构类似于
{
"en": {
"translation": {
"name": "Name",
"description": ["I am a", "en person"]
}
},
"jp": {
"translation": {
"name": "JP Name",
"description": ["I am a", "jp person"]
}
}
}
所以我只想将它们解析为 newtype Translations = Map String String
之类的东西。语言环境将是键名,值将只是 JSON 翻译的字符串,如 {"name": "Name", "description": ["I am a", en person"]}
,因为该值可以任意复杂,我不想 care/need 将其转换为其他 Haskell 数据结构。
我试了很多方法为 Translation
写一个合适的 parseJSON
但还是做不到。
如有任何帮助,我们将不胜感激!
我们可以解码ByteString
:
Prelude Data.Aeson Bs Hm Mp Tx> decode text :: Maybe Object
Just (fromList [("jp",Object (fromList [("translation",Object (fromList [("name",String "JP Name"),("description",Array [String "I am a",String "jp person"])]))])),("en",Object (fromList [("translation",Object (fromList [("name",String "Name"),("description",Array [String "I am a",String "en person"])]))]))])
那么我们只需要对包裹在`Object构造函数中的HashMap Text Object
进行映射:
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as Bs
import qualified Data.HashMap.Lazy as Hm
import qualified Data.Map as Mp
import qualified Data.Text as Tx
process :: Value -> Maybe (Mp.Map String String)
process (Object m) = Just ((Mp.fromList . map f) (Hm.toList m))
where f (x, y) = (Tx.unpack x, Bs.unpack (encode y))
process _ = Nothing
然后我们得到一个包裹在Maybe
中的Map String String
(因为两者都解码,并且处理可能出错,所以使用Maybe
可能更好),即映射String
s 在 String
s:
Prelude Data.Aeson Bs Hm Mp Tx> decode text >>= process
Just (fromList [("en","{\"translation\":{\"name\":\"Name\",\"description\":[\"I am a\",\"en person\"]}}"),("jp","{\"translation\":{\"name\":\"JP Name\",\"description\":[\"I am a\",\"jp person\"]}}")])
也就是说,我不确定 JSON 作为值的 blob 是否是您想要的,因为现在不能 "look into" 该值并检查该元素中的内容。此外,如果您想进行大量查找,当您想检查两个 Text
是否相同时,Text
通常会快一个数量级。