簡體   English   中英

我可以在Data.Aeson和Data.Yaml之間重用ToJSON和FromJSON實例嗎?

[英]Can I reuse ToJSON and FromJSON instances between Data.Aeson and Data.Yaml?

Data.Aeson和Data.Yaml是分別用於JSON和YAML的庫,它們具有幾乎相同的接口。 我為某些類型編寫了“基於Aeson的” FromJSONToJSON實例:

import Data.Aeson

data PropertyValue = Nested Microformat | Flat Text
    deriving (Generic, Show)

instance ToJSON PropertyValue where
    toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }

instance FromJSON PropertyValue where
    parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }

雖然Aeson使用這些實例,但Yaml似乎忽略了它們。 (特別是,我相信Yaml會自動生成編碼器和解碼器,這要歸功於我的類型派生了Generic 。)我試圖通過將代碼更改為Yaml,使實例也能與Yaml一起使用

import Data.Aeson
import qualified Data.Yaml as Y

data PropertyValue = Nested Microformat | Flat Text
    deriving (Generic, Show)

instance ToJSON PropertyValue where
    toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }

instance FromJSON PropertyValue where
    parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }

instance Y.ToJSON PropertyValue where
    toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }

instance Y.FromJSON PropertyValue where
    parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }

但GHC抱怨:

Duplicate instance declarations:
  instance ToJSON PropertyValue
    -- Defined at src/Microformats.hs:54:10
  instance ToJSON PropertyValue
    -- Defined at src/Microformats.hs:60:10

是否無法為碰巧具有相同名稱的兩個不同類定義實例? 還是Yaml的ToJSON實際上 Aeson的類相同

更重要的是,是否有可能重用我的ToJSONFromJSON實例,而不必兩次編寫相同的代碼? 失敗了,是否至少可以在不混淆編譯器的情況下編寫兩個庫的ToJSONFromJSON實例?

簡短的回答 :在ToJSON (和FromJSON的)類型類Data.AesonData.Yaml 是相同的 Data.Yaml實際上只執行的重新導入 ToJSON的類型類Data.Aeson

如果我們看一下Data.Yaml源代碼

 #if (defined (ghcjs_HOST_OS)) module Data.Yaml {-# WARNING "GHCJS is not supported yet (will break at runtime once called)." #-} #else module Data.Yaml #endif ( -- * Types Value (..) , Parser , Object , Array , ParseException(..) , prettyPrintParseException , YamlException (..) , YamlMark (..) -- * Constructors and accessors , object , array , (.=) , (.:) , (.:?) , (.!=) -- ** With helpers (since 0.8.23) , withObject , withText , withArray , withScientific , withBool -- * Parsing , parseMonad , parseEither , parseMaybe -- * Classes , ToJSON (..) , FromJSON (..) -- * Encoding/decoding , encode , encodeFile , decode , decodeFile -- ** Better error information , decodeEither , decodeEither' , decodeFileEither -- ** More control over decoding , decodeHelper ) where #if !MIN_VERSION_base(4,8,0) import Control.Applicative(()) #endif import Control.Exception import Data.Aeson ( Value (..), ToJSON (..), FromJSON (..) , object , (.=) , (.:) , (.:?) , (.!=) , Object, Array , withObject, withText, withArray, withScientific, withBool ) 
(......)

因此,模塊將導出ToJSON類型類,但這僅是ToJSON導入的Data.Aeson ,因此類型類實際上是完全相同的。

因此,為了方便程序員而將其重新導入(例如,您不必導入Data.Aeson僅實現FromJOSN ),但實際上您仍然使用相同的類型,相同的類型類等。畢竟, ToJSONY.ToJSON引用相同的類型類。

由於兩者實際上是相同的,因此您無法為相同類型實例化相同的類型類兩次,但是我們不需要這樣做:如果我們為Data.Aeson (或Data.Yaml )實現它, Data.Aeson足夠了,因為例如,用Data.Yaml (或Data.Aeson )編寫的類型類約束將成功。 結果是,我們不能(至少沒有一些技巧) ToJSON不同於Data.Yaml實現Data.Aeson

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM