如何正确实现FromJSON我的数据类型?

时间:2022-09-02 12:05:37

I have a data with a few constructors:

我有几个构造函数的数据:

data MyData = 
  A1 { var1 :: Int, var2 :: String }
  A2 { var1 :: Int, var2 :: String, var3 :: Char }
  A3 { var1 :: Int, var2 :: Char, var3 :: String, var4 :: String }

This is a simplified version of my real "data". Without using deriving (Generic), how can I implement it for the class ToJSON?

这是我真实“数据”的简化版本。不使用deriving(Generic),如何为类ToJSON实现它?

instance FromJSON MyData where
  parseJSON (Object v) = do
    .. --- how do I know if v is created by A1 or A2 or A3?

1 个解决方案

#1


2  

Aeson's Parser is an instance of Alternative. As such, you can provide multiple parsers and combine them with (<|>):

Aeson的Parser是Alternative的一个实例。因此,您可以提供多个解析器并将它们与(<|>)组合:

{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative ((<|>))
import Data.Aeson

-- Removed record fields to keep things short, but you can put them back.
data MyData = A1 Int String
            | A2 Int String Char
            | A3 Int Char   String String
            deriving Show

instance FromJSON MyData where
  parseJSON (Object v) =  A3 <$> v .: "var1" <*> v .: "var2" <*> v .: "var3" <*> v .: "var4" 
                      <|> A2 <$> v .: "var1" <*> v .: "var2" <*> v .: "var3"
                      <|> A1 <$> v .: "var1" <*> v .: "var2"

Note that the order of parsers is important, since v .: "var1" and v .: "var2" succeed for all three parsers.

请注意,解析器的顺序很重要,因为v。:“var1”和v。:“var2”对所有三个解析器都成功。

#1


2  

Aeson's Parser is an instance of Alternative. As such, you can provide multiple parsers and combine them with (<|>):

Aeson的Parser是Alternative的一个实例。因此,您可以提供多个解析器并将它们与(<|>)组合:

{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative ((<|>))
import Data.Aeson

-- Removed record fields to keep things short, but you can put them back.
data MyData = A1 Int String
            | A2 Int String Char
            | A3 Int Char   String String
            deriving Show

instance FromJSON MyData where
  parseJSON (Object v) =  A3 <$> v .: "var1" <*> v .: "var2" <*> v .: "var3" <*> v .: "var4" 
                      <|> A2 <$> v .: "var1" <*> v .: "var2" <*> v .: "var3"
                      <|> A1 <$> v .: "var1" <*> v .: "var2"

Note that the order of parsers is important, since v .: "var1" and v .: "var2" succeed for all three parsers.

请注意,解析器的顺序很重要,因为v。:“var1”和v。:“var2”对所有三个解析器都成功。