让 ToJSON 使用 Show Instance
Making ToJSON use Show Instance
如果我的数据类型如下所示:
data SumType = ABC | DEF deriving (Generic, ToJSON)
data MyType = MyType {field1 :: String, field2 :: SumType} deriving (Generic, ToJSON)
以上将生成一个 JSON,如下所示:{"field1": "blah", "field2":"ABC"}
实际上,MyType
是一种相当复杂的类型,我想保持 ToJSON
派生,但只想调整一个字段以使用 show 实例。
instance Show SumType where
show ABC = "abc-blah"
show DEF = "def-xyz"
不幸的是,上面的 Show
实例没有被 ToJSON
拾取(我不知道它是否应该被拾取)。为 SumType
手动滚动 ToJSON
似乎 不起作用,因为它需要一个键值对(也许还有另一种方法吗?)。换句话说,JSON 将类似于:{"field1": "blah", "field2":{"field3": "ABC"}}
——我只想更改值的字符串化方式,而不是在那里创建新对象。
关于如何在不为 MyType
手动创建 ToJSON
的情况下更改 SumType
的输出字符串的任何建议?所以输出是 {"field1": "blah", "field2":"abc-blah"}
谢谢!
我不明白为 SumType
定义 ToJSON
实例有什么问题。你可以这样做:
import Data.Aeson(ToJSON(toJSON), Value(String))
import Data.Text(pack)
instance ToJSON SumType where
toJSON = String . pack . show
或者如果您想为 ToJSON
使用 Show
之外的其他字符串:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson(ToJSON(toJSON), Value(String))
instance ToJSON SumType where
toJSON ABC = String "ABC for JSON"
toJSON DEF = String "DEF for JSON"
现在 Haskell 将 JSON 将 SumType
编码为 JSON 字符串:
Prelude Data.Aeson> encode ABC
"\"ABC for JSON\""
Prelude Data.Aeson> encode DEF
"\"DEF for JSON\""
您可以对 FromJSON
执行相同的操作,将 JSON 字符串解析回 SumType
对象:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson(FromJSON(parseJSON), withText)
instance FromJSON SumType where
parseJSON = withText "SumType" f
where f "ABC for JSON" = return ABC
f "DEF for JSON" = return DEF
f _ = fail "Can not understand what you say!"
如果我们再解析回 JSON 字符串,我们会得到:
Prelude Data.Aeson> decode "\"ABC for JSON\"" :: Maybe SumType
Just ABC
Prelude Data.Aeson> decode "\"DEF for JSON\"" :: Maybe SumType
Just DEF
Prelude Data.Aeson> decode "\"other JSON string\"" :: Maybe SumType
Nothing
Prelude Data.Aeson> decode "{}" :: Maybe SumType
Nothing
因此,如果我们不解码遵循我们定义的模式之一的 JSON 字符串,解析将失败。如果我们不提供 JSON 字符串,而是提供一个空的 JSON 对象,也会发生同样的情况。
Additional notes:
- Since
SumType
here has two values, you can also use a JSON boolean to encode the values.
- you can also encode on different JSON objects. You can for instance use the JSON string for
ABC
, and an integer for DEF
.
Although I would advice not to do this until there are good reasons
(if for instance ABC
carries only a string, and DEF
ony an
integer).
- usually the more complex you make encoding, the more complex decoding will be.
如果我的数据类型如下所示:
data SumType = ABC | DEF deriving (Generic, ToJSON)
data MyType = MyType {field1 :: String, field2 :: SumType} deriving (Generic, ToJSON)
以上将生成一个 JSON,如下所示:{"field1": "blah", "field2":"ABC"}
实际上,MyType
是一种相当复杂的类型,我想保持 ToJSON
派生,但只想调整一个字段以使用 show 实例。
instance Show SumType where
show ABC = "abc-blah"
show DEF = "def-xyz"
不幸的是,上面的 Show
实例没有被 ToJSON
拾取(我不知道它是否应该被拾取)。为 SumType
手动滚动 ToJSON
似乎 不起作用,因为它需要一个键值对(也许还有另一种方法吗?)。换句话说,JSON 将类似于:{"field1": "blah", "field2":{"field3": "ABC"}}
——我只想更改值的字符串化方式,而不是在那里创建新对象。
关于如何在不为 MyType
手动创建 ToJSON
的情况下更改 SumType
的输出字符串的任何建议?所以输出是 {"field1": "blah", "field2":"abc-blah"}
谢谢!
我不明白为 SumType
定义 ToJSON
实例有什么问题。你可以这样做:
import Data.Aeson(ToJSON(toJSON), Value(String))
import Data.Text(pack)
instance ToJSON SumType where
toJSON = String . pack . show
或者如果您想为 ToJSON
使用 Show
之外的其他字符串:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson(ToJSON(toJSON), Value(String))
instance ToJSON SumType where
toJSON ABC = String "ABC for JSON"
toJSON DEF = String "DEF for JSON"
现在 Haskell 将 JSON 将 SumType
编码为 JSON 字符串:
Prelude Data.Aeson> encode ABC
"\"ABC for JSON\""
Prelude Data.Aeson> encode DEF
"\"DEF for JSON\""
您可以对 FromJSON
执行相同的操作,将 JSON 字符串解析回 SumType
对象:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson(FromJSON(parseJSON), withText)
instance FromJSON SumType where
parseJSON = withText "SumType" f
where f "ABC for JSON" = return ABC
f "DEF for JSON" = return DEF
f _ = fail "Can not understand what you say!"
如果我们再解析回 JSON 字符串,我们会得到:
Prelude Data.Aeson> decode "\"ABC for JSON\"" :: Maybe SumType
Just ABC
Prelude Data.Aeson> decode "\"DEF for JSON\"" :: Maybe SumType
Just DEF
Prelude Data.Aeson> decode "\"other JSON string\"" :: Maybe SumType
Nothing
Prelude Data.Aeson> decode "{}" :: Maybe SumType
Nothing
因此,如果我们不解码遵循我们定义的模式之一的 JSON 字符串,解析将失败。如果我们不提供 JSON 字符串,而是提供一个空的 JSON 对象,也会发生同样的情况。
Additional notes:
- Since
SumType
here has two values, you can also use a JSON boolean to encode the values.- you can also encode on different JSON objects. You can for instance use the JSON string for
ABC
, and an integer forDEF
. Although I would advice not to do this until there are good reasons (if for instanceABC
carries only a string, andDEF
ony an integer).- usually the more complex you make encoding, the more complex decoding will be.