使用Aeson/JSON处理派生的Aeson FromJSON实例中的`id`

mat*_*ias 6 generics json haskell custom-data-type aeson

如果我有,JSON并且我尝试FromJSON自动派生实例Generics,我遇到问题,id存在于多个地方JSON.

有没有办法让我只覆盖id部分或者我必须编写整个实例才能更改这些特定的条目?在JSON实际上有更多的领域,但我最左侧的它在这个例子.因此,写出整个FromJSON实例实际上是相当繁琐的.

JSON:

{
  "response": [
    {
      "id": 1,
      "brandId": 1,
      "productTypeId": 1,
      "identity": {
        "sku": "x",
        "barcode": "Ax"
      },
      "stock": {
        "stockTracked": false,
        "weight": {
          "magnitude": 0
        },
        "dimensions": {
          "length": 0,
          "height": 0,
          "width": 0,
          "volume": 0
        }
      },
      "financialDetails": {
        "taxable": false,
        "taxCode": {
          "id": 1,
          "code": "x"
        }
      },
... etc
  ]
}
Run Code Online (Sandbox Code Playgroud)

代码到目前为止:

data Response = Response
    { response :: [Body]
    } deriving (Show,Generic)

data Body = Body
    { id                    :: Int
    , brandId               :: Int
    , productTypeId         :: Int
    , identity              :: Identity
    , productGroupId        :: Int
    , stock                 :: Stock
    , financialDetails      :: FinancialDetails
    } deriving (Show,Generic)                  

data Identity = Identity
    { sku       :: String
    , ean       :: String
    , barcode   :: String
    } deriving (Show,Generic)                  

data Stock = Stock
    { stockTracked  :: Bool
    , weight        :: Weight
    , dimensions    :: Dimensions
    } deriving (Show,Generic)                  

data Weight = Weight
    { magnitude  :: Int
    } deriving (Show,Generic)                  

data Dimensions = Dimensions
    { length :: Int
    , height :: Int
    , width  :: Int
    , volume :: Int
    } deriving (Show,Generic)                  

data FinancialDetails = FinancialDetails
     { taxable :: Bool
     , taxCode :: TaxCode
     } deriving (Show,Generic)                  

data TaxCode = TaxCode
     { id      :: Int
     , code    :: String 
     } deriving (Show,Generic)                  


instance FromJSON Response
instance FromJSON Body
instance FromJSON Identity
instance FromJSON Stock
instance FromJSON Weight
instance FromJSON Dimensions
instance FromJSON FinancialDetails
Run Code Online (Sandbox Code Playgroud)

这给出了错误:

[1 of 1] Compiling Main             ( reponse.hs, interpreted )

response.hs:73:8:
    Multiple declarations of `id'
    Declared at: response.hs:19:7
                 response.hs:73:8
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想改变第一idbody_id,第二次taxCode_id,而无需编写出整个实例.

zak*_*aps 11

在派生FromJSON实例时,您可以将选项传递给该genericParseJSON函数.这通常是

data Foo = {- ... -} deriving (Show, Generic)

instance FromJSON Foo where
    parseJSON = genericParseJSON defaultOptions
    -- defaultOptions :: Options
Run Code Online (Sandbox Code Playgroud)

虽然你可以defaultOptionsOption你手工构造的替换.该Option类型具有fieldLabelModifier可以预处理数据类型的字段名称的字段.您可以将数据类型定义为

data Body = Body
  { body_id :: Int
  ...
Run Code Online (Sandbox Code Playgroud)

并编写一个辅助函数,映射"body_id""id"和其他任何不变的:

body_noprefix "body_id" = "id"
body_noprefix s = s
Run Code Online (Sandbox Code Playgroud)

然后将实例定义为

instance FromJSON Body where
  parseJSON = genericParseJSON (defaultOptions { fieldLabelModifier = body_noprefix })
Run Code Online (Sandbox Code Playgroud)