如果我的数据类型如下所示:
py2app
以上将生成一个类似于:data SumType = ABC | DEF deriving (Generic, ToJSON)
data MyType = MyType {field1 :: String, field2 :: SumType} deriving (Generic, ToJSON)
在实践中,{"field1": "blah", "field2":"ABC"}
是一个相当复杂的类型,我想保持MyType
派生但想要调整一个字段来使用show实例。
ToJSON
不幸的是,上述 instance Show SumType where
show ABC = "abc-blah"
show DEF = "def-xyz"
实例未被Show
提取(我不知道是否应该这样做)。 ToJSON
的{{1}}手动似乎无法正常工作,因为它需要一个键值对(也许有另一种方法可以做到这一点?)。换句话说,JSON将类似于:ToJSON
- 我只想更改值的字符串化方式,而不是在那里创建新对象。
关于如何在不为SumType
手动创建{"field1": "blah", "field2":{"field3": "ABC"}}
的情况下更改SumType
的输出字符串的任何建议?因此输出为ToJSON
谢谢!
答案 0 :(得分:2)
我没有看到为ToJSON
定义SumType
实例的问题。你可以这样做:
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对象,则会发生同样的情况。
附加说明:
- 由于
SumType
此处有两个值,您还可以使用JSON布尔值对值进行编码。- 您还可以对不同的JSON对象进行编码。例如,您可以使用
ABC
的JSON字符串和DEF
的整数。 虽然我建议不要在有充分理由之前这样做 (例如,如果ABC
只携带一个字符串,DEF
只能携带一个字符串 整数)。- 通常编码越复杂,解码就越复杂。
醇>