2017-11-01 5 views
2

を使用して作る:MyTypeはかなり複雑なタイプで、実際には{"field1": "blah", "field2":"ABC"}ToJSONが、私はこのようになり、データ型がある場合は表示インスタンス

data SumType = ABC | DEF deriving (Generic, ToJSON) 
data MyType = MyType {field1 :: String, field2 :: SumType} deriving (Generic, ToJSON) 

を上記のように見えますJSONを生成します。 ToJSONは派生していますが、showインスタンスを使用するフィールドを1つだけ調整したいと考えています。

instance Show SumType where 
    show ABC = "abc-blah" 
    show DEF = "def-xyz" 

残念ながら、上記のShowインスタンスは(それがすることになっている場合、私は知らない)ToJSONによってピックアップされません。ハンドローリングToJSONSumTypeではありませんと思われます。キーと値のペアが必要です(別の方法がありますか?)。言い換えれば、JSONは次のようになります:{"field1": "blah", "field2":{"field3": "ABC"}} - 値を文字列化して新しいオブジェクトを作成しない方法を変更したいだけです。

に対して手動でToJSONを作成せずに出力文字列をSumTypeに変更する方法についてのご意見はありますか?だから出力は{"field1": "blah", "field2":"abc-blah"}

ありがとう!

+1

「SumType」に「ToJSON」を作成する際の問題点は何ですか? 'Show SumType'で定義を使うことができます。 –

+0

@WillemVanOnsem私は 'ToJSON'は'オブジェクト 'しか受け入れないと思った。私はちょうど文字列を返すことができるのか分からなかった。答えに答えを入れると、私はそれを受け入れることができます。 – Ecognium

答えて

2

SumTypeToJSONインスタンスを定義する際に問題が何も表示されません。あなたがこれを行うことができます。

:JSON文字列として

{-# 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

import Data.Aeson(ToJSON(toJSON), Value(String)) 
import Data.Text(pack) 

instance ToJSON SumType where 
    toJSON = String . pack . show 

それともToJSONShow以外のために他の文字列を使用する場合

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文字列をバック解析する場合は、我々が得る:だから場合には、我々は我々が定義したパターンのいずれかを次の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オブジェクトなど)は同じことが起こります。

その他の注意事項:ここでは2つの値を持つ

  1. SumTypeので、あなたも値をエンコードするためにJSONのブール値を使用することができます。
  2. 異なるJSONオブジェクトでエンコードすることもできます。たとえば、ABCのJSON文字列とDEFの整数を使用できます。 良い理由があるまでは、私は助言しますが、 (例えば、ABCは文字列のみを持ち、DEFは の整数です)。
  3. 通常、エンコードを複雑にするほど、より複雑なデコードが行われます。
+0

'' WithType''に渡された '' SumType''は何ですか?他の方法で解析する際にエラーメッセージを変更しますか?それは実証するのが良いかもしれません。 – dfeuer

関連する問題