haskell 使用Aeson解析JSON以MapString String

yws3nbqq  于 2023-11-18  发布在  其他
关注(0)|答案(2)|浏览(143)

我尝试从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这样的东西。locale将是键值,值将是JSON翻译的字符串,比如{"name": "Name", "description": ["I am a", en person"]},因为值可以是任意复杂的,我不关心/需要把它转换成其他Haskell数据结构。
我尝试了很多方法来为Translation写一个合适的parseJSON,但仍然无法实现。
任何帮助将不胜感激!

nhjlsmyf

nhjlsmyf1#

我们可以通过以下方式解码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构造函数中 Package 的HashMap Text Object`上执行Map:

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


然后我们得到一个Map String String,它被一个Maybe包裹(因为解码和处理都可能出错,所以最好使用一个Maybe),它将String sMap到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作为值是否是你想要的,因为现在你不能“查看”值并检查元素内部的内容。此外,如果你想做很多查找,当你想检查两个Text是否相同时,Text通常要快一个数量级。

lokaqttq

lokaqttq2#

MapHashMap都有FromJSON的示例。所以不需要在Object构造函数上匹配,你可以只指定所需的类型和Aeson.decode

> import qualified Data.Aeson as Aeson
> import Data.Map as Map
> let Just obj = Aeson.decode str :: Maybe (Map String Aeson.Value)

> obj
fromList [("jp",Object (fromList [("translation",Object (fromList [("description",Array [String "I am a",String "jp person"]),("name",String "JP Name")]))])),("en",Object (fromList [("translation",Object (fromList [("description",Array [String "I am a",String "en person"]),("name",String "Name")]))]))]

> mapM_ print $ Map.toList $ Map.map Aeson.encode obj
("jp","{\"translation\":{\"description\":[\"I am a\",\"jp person\"],\"name\":\"JP Name\"}}")
("en","{\"translation\":{\"description\":[\"I am a\",\"en person\"],\"name\":\"Name\"}}")

字符串

相关问题