Anonymous avatar Anonymous committed 2b9db9d

Change toJSON and fromJSON instances for Either.

Previously, fromJSON . toJSON == id was violated by the Either
instances. In addition, if both types are parsable from the same
JSON, then the Left is always given favor - which is probably not
desirable. Instead, differentiate the instances using an array.

This allows for "Either a a" to actually work instead of always
chosing Left in FromJSON.

Comments (0)

Files changed (1)

Data/Aeson/Types.hs

     {-# INLINE parseJSON #-}
 
 instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where
-    toJSON (Left a)  = toJSON a
-    toJSON (Right b) = toJSON b
+    toJSON (Left a)  = Array (V.fromList [String "Left", toJSON a])
+    toJSON (Right b) = Array (V.fromList [String "Right", toJSON b])
     {-# INLINE toJSON #-}
     
 instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where
-    parseJSON a = Left <$> parseJSON a <|> Right <$> parseJSON a
+    parseJSON v@(Array vec) =
+        if V.length vec /= 2
+            then typeMismatch "Either a b" v
+            else case vec V.! 0 of
+                "Left" -> Left <$> parseJSON (vec V.! 1)
+                "Right" -> Right <$> parseJSON (vec V.! 1)
+                _ -> typeMismatch "Either a b" v
+    parseJSON v         = typeMismatch "Either a b" v
     {-# INLINE parseJSON #-}
 
 instance ToJSON Bool where
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.