使ToJSON使用Show Instance

时间:2017-11-01 15:43:45

标签: haskell aeson

如果我的数据类型如下所示:

py2app

以上将生成一个类似于:data SumType = ABC | DEF deriving (Generic, ToJSON) data MyType = MyType {field1 :: String, field2 :: SumType} deriving (Generic, ToJSON)

的JSON

在实践中,{"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

谢谢!

1 个答案:

答案 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对象,则会发生同样的情况。

  

附加说明

     
      
  1. 由于SumType此处有两个值,您还可以使用JSON布尔值对值进行编码。
  2.   
  3. 您还可以对不同的JSON对象进行编码。例如,您可以使用ABC的JSON字符串和DEF的整数。   虽然我建议不要在有充分理由之前这样做   (例如,如果ABC只携带一个字符串,DEF只能携带一个字符串   整数)。
  4.   
  5. 通常编码越复杂,解码就越复杂。
  6.