具有自定义键类型的 Data.Map.Strict.Map 的 Aeson 编码导致数组数组而不是对象
Aeson encoding of Data.Map.Strict.Map with custom key type results in array of arrays instead of object
当我使用自定义类型作为键时,我无法让 Aeson 吐出对象。让我演示一下:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Aeson
import qualified Data.Map.Strict as M
import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Generics
data LOL = A | B | C deriving (Eq, Ord, Generic, ToJSONKey, ToJSON)
main = do
B.putStrLn $ encode $ M.fromList [(A,"b")]
B.putStrLn $ encode $ M.fromList [("A","b")]
在一种情况下,我得到一个数组数组,而在另一种情况下,它是一个常规对象:
$ ./tojsonkey
[["A","b"]]
{"A":"b"}
有什么想法吗?
看看the docs for ToJSONKey
。基本上,toJSONKey :: ToJSONKeyFunction a
方法处理两种情况:
- 何时可以将密钥直接转换为类似
的文本
- 当你能做的最好的事情就是把钥匙变成一些通用的 JSON
对于第一个,aeson
将使用适当的 JSON 对象。对于后者,它会退回到嵌套数组。
那么为什么在您的情况下选择选项二?因为您正在派生 ToJSONKey
并且默认实现选择第二个更通用的选项。您可以通过手动实施 ToJSONKey LOL
:
来解决此问题
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Aeson
import Data.Aeson.Types
import qualified Data.Text as T
import qualified Data.Map.Strict as M
import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Generics
data LOL = A | B | C deriving (Eq, Ord, Show, Generic, ToJSON)
instance ToJSONKey LOL where
toJSONKey = toJSONKeyText (T.pack . show)
main = do
B.putStrLn $ encode $ M.fromList [(A,"b")]
B.putStrLn $ encode $ M.fromList [("A","b")]
那应该给你
$ ./tojsonkey
{"A":"b"}
{"A":"b"}
当我使用自定义类型作为键时,我无法让 Aeson 吐出对象。让我演示一下:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Aeson
import qualified Data.Map.Strict as M
import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Generics
data LOL = A | B | C deriving (Eq, Ord, Generic, ToJSONKey, ToJSON)
main = do
B.putStrLn $ encode $ M.fromList [(A,"b")]
B.putStrLn $ encode $ M.fromList [("A","b")]
在一种情况下,我得到一个数组数组,而在另一种情况下,它是一个常规对象:
$ ./tojsonkey
[["A","b"]]
{"A":"b"}
有什么想法吗?
看看the docs for ToJSONKey
。基本上,toJSONKey :: ToJSONKeyFunction a
方法处理两种情况:
- 何时可以将密钥直接转换为类似 的文本
- 当你能做的最好的事情就是把钥匙变成一些通用的 JSON
对于第一个,aeson
将使用适当的 JSON 对象。对于后者,它会退回到嵌套数组。
那么为什么在您的情况下选择选项二?因为您正在派生 ToJSONKey
并且默认实现选择第二个更通用的选项。您可以通过手动实施 ToJSONKey LOL
:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Aeson
import Data.Aeson.Types
import qualified Data.Text as T
import qualified Data.Map.Strict as M
import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Generics
data LOL = A | B | C deriving (Eq, Ord, Show, Generic, ToJSON)
instance ToJSONKey LOL where
toJSONKey = toJSONKeyText (T.pack . show)
main = do
B.putStrLn $ encode $ M.fromList [(A,"b")]
B.putStrLn $ encode $ M.fromList [("A","b")]
那应该给你
$ ./tojsonkey
{"A":"b"}
{"A":"b"}