gpt4 book ai didi

haskell - Haskell在记录字段中的保留关键字如何处理?

转载 作者:行者123 更新时间:2023-12-04 06:14:55 25 4
gpt4 key购买 nike

JSON 响应 Github Gists Rest API包含 Haskell's keyword type .但是type不能用作记录字段。

因此它不能用于 Aeson's Generic 的实现。 FromJSON/ToJSON 实例。

import Data.Text (Text)

import GHC.Generics (Generic)

type URL = Text

data OwnerType = User deriving (Show)

data Owner = Owner {
id :: Int,
gravatar_id :: Text,
login :: Text,
avatar_url :: Text,
events_url :: URL,
followers_url :: URL,
following_url :: URL,
gists_url :: URL,
html_url :: URL,
organizations_url :: URL,
received_events_url :: URL,
repos_url :: URL,
starred_url :: URL,
subscriptions_url :: URL,
url :: URL,
-- type :: Text,
site_admin :: Bool
} deriving (Generic, Show)

instance ToJSON Owner
instance FromJSON Owner

问题 :
是否有适当的方法来处理此类冲突?

最佳答案

我们可以使用 TemplateHaskell 来解决这个问题。 .而不是写 ToJSONFromJON ,我们可以使用特定的键映射。

首先,我们必须为非类型字段构造一个名称,例如:

data Owner = Owner {
id :: Int,
gravatar_id :: Text,
login :: Text,
avatar_url :: Text,
events_url :: URL,
followers_url :: URL,
following_url :: URL,
gists_url :: URL,
html_url :: URL,
organizations_url :: URL,
received_events_url :: URL,
repos_url :: URL,
starred_url :: URL,
subscriptions_url :: URL,
url :: URL,
owner_type :: Text,
site_admin :: Bool
} deriving (Generic, Show)

现在我们可以使用 deriveJSON :: Options -> Name -> Q [Dec] 将构造 fromJSON 的函数和 toJSON实例。

这里的关键是 Options 参数:它包含一个 fieldLabelModifier :: String -> String 可以将字段名称重写为 JSON 中的键的字段。因此,我们可以在这里生成一个将重写它的函数。

所以我们先构造一个函数 ownerFieldRename :: String -> String :
ownerFieldRename :: String -> String
ownerFieldRename "owner_type" = "type"
ownerFieldRename name = name

所以这个函数作为一个恒等函数,除了 "owner_type" , 映射到 "type" .

所以现在我们可以调用 deriveJSON具有自定义选项的功能,例如:
$(deriveJSON defaultOptions {fieldLabelModifier = ownerFieldRename} ''Owner)

或全部:

RenameUtils.hs :
module RenameUtils where

ownerFieldRename :: String -> String
ownerFieldRename "owner_type" = "type"
ownerFieldRename name = name

MainFile.hs :
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}

import Data.Aeson.TH(deriveJSON, defaultOptions, Options(fieldLabelModifier))
import RenameUtils(ownerFieldRename)

import Data.Text (Text)

type URL = Text

data Owner = Owner {
id :: Int,
gravatar_id :: Text,
login :: Text,
avatar_url :: Text,
events_url :: URL,
followers_url :: URL,
following_url :: URL,
gists_url :: URL,
html_url :: URL,
organizations_url :: URL,
received_events_url :: URL,
repos_url :: URL,
starred_url :: URL,
subscriptions_url :: URL,
url :: URL,
owner_type :: Text,
site_admin :: Bool
} deriving (Show)

$(deriveJSON defaultOptions {fieldLabelModifier = ownerFieldRename} ''Owner)

现在我们用 type 获得一个 JSON 对象。作为关键:
Prelude Main Data.Aeson> encode (Owner 1 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" True)
"{\"id\":1,\"gravatar_id\":\"\",\"login\":\"\",\"avatar_url\":\"\",\"events_url\":\"\",\"followers_url\":\"\",\"following_url\":\"\",\"gists_url\":\"\",\"html_url\":\"\",\"organizations_url\":\"\",\"received_events_url\":\"\",\"repos_url\":\"\",\"starred_url\":\"\",\"subscriptions_url\":\"\",\"url\":\"\",\"type\":\"\",\"site_admin\":true}"

对于一个简单的 fieldLabelModifier function 我们不需要编写特定的函数(我们必须在特定的模块中定义),我们也可以在这里使用 lambda 表达式:

MainFile.hs :
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}

import Data.Aeson.TH(deriveJSON, defaultOptions, Options(fieldLabelModifier))
import Data.Text (Text)

type URL = Text

data Owner = Owner {
id :: Int,
gravatar_id :: Text,
login :: Text,
avatar_url :: Text,
events_url :: URL,
followers_url :: URL,
following_url :: URL,
gists_url :: URL,
html_url :: URL,
organizations_url :: URL,
received_events_url :: URL,
repos_url :: URL,
starred_url :: URL,
subscriptions_url :: URL,
url :: URL,
owner_type :: Text,
site_admin :: Bool
} deriving (Show)

$(deriveJSON defaultOptions {fieldLabelModifier = \x -> if x == "owner_type" then "type" else x} ''Owner)

关于haskell - Haskell在记录字段中的保留关键字如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48474587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com