Json 使用文本键将序列化中的键名功能性更改为aeson
我有一个json对象,其中有一个手工制作的ToJSON实例。我想用一个不需要显式枚举键名的函数来替换它 我使用“rec*”作为前缀,我想去掉它,我的字段开始时是文本而不是字符串 从最少的数据开始:Json 使用文本键将序列化中的键名功能性更改为aeson,json,haskell,text,aeson,Json,Haskell,Text,Aeson,我有一个json对象,其中有一个手工制作的ToJSON实例。我想用一个不需要显式枚举键名的函数来替换它 我使用“rec*”作为前缀,我想去掉它,我的字段开始时是文本而不是字符串 从最少的数据开始: data R3 = R3 { recCode :: Code , recValue :: Value} deriving (Show, Generic) 和智能构造函数功能: makeR3 rawcode rawval = R3 code value where
data R3 = R3 { recCode :: Code
, recValue :: Value} deriving (Show, Generic)
和智能构造函数功能:
makeR3 rawcode rawval = R3 code value where
code = rawcode
value = rawval
此实现工作正常:
instance ToJSON R3 where
toJSON (R3 recCode recValue) = object [ "code" .= recCode, "value" .= recValue]
但正如您所想象的,我不想手工将每个键名从“code”输入到“recCode”
tmp_r3 = makeR3 "TD" "100.42"
as_json = encode tmp_r3
main = do
let out = encodeToLazyText tmp_r3
I.putStrLn out
I.writeFile "./so.json" out
return ()
输出正确:
{"value":100.42,"code":"TD"}
-- not recValue and recCode, correct!
但是,当我尝试此函数时,它无法像以前那样自动将文本转换为字符串
instance ToJSON R3 where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = T.toLower . IHaskellPrelude.drop 3 }
输出:
<interactive>:8:35: error:
• Couldn't match type ‘Text’ with ‘String’
Expected type: String -> String
Actual type: String -> Text
• In the ‘fieldLabelModifier’ field of a record
In the first argument of ‘genericToJSON’, namely ‘defaultOptions {fieldLabelModifier = toLower . IHaskellPrelude.drop 3}’
In the expression: genericToJSON defaultOptions {fieldLabelModifier = toLower . IHaskellPrelude.drop 3}
<interactive>:8:47: error:
• Couldn't match type ‘String’ with ‘Text’
Expected type: String -> Text
Actual type: String -> String
• In the second argument of ‘(.)’, namely ‘IHaskellPrelude.drop 3’
In the ‘fieldLabelModifier’ field of a record
In the first argument of ‘genericToJSON’, namely ‘defaultOptions {fieldLabelModifier = toLower . IHaskellPrelude.drop 3}’
在:
我得到:
<interactive>:8:35: error:
• Couldn't match type ‘Char’ with ‘String’
Expected type: String -> String
Actual type: String -> Char
• In the ‘fieldLabelModifier’ field of a record
In the first argument of ‘genericToJSON’, namely ‘defaultOptions {fieldLabelModifier = Data.Char.toLower . IHaskellPrelude.drop 3}’
In the expression: genericToJSON defaultOptions {fieldLabelModifier = Data.Char.toLower . IHaskellPrelude.drop 3}
<interactive>:8:55: error:
• Couldn't match type ‘String’ with ‘Char’
Expected type: String -> Char
Actual type: String -> String
• In the second argument of ‘(.)’, namely ‘IHaskellPrelude.drop 3’
In the ‘fieldLabelModifier’ field of a record
In the first argument of ‘genericToJSON’, namely ‘defaultOptions {fieldLabelModifier = Data.Char.toLower . IHaskellPrelude.drop 3}’
:8:35:错误:
•无法将类型“Char”与“String”匹配
预期类型:字符串->字符串
实际类型:String->Char
•在记录的“fieldLabelModifier”字段中
在“genericToJSON”的第一个参数中,即“defaultOptions{fieldLabelModifier=Data.Char.toLower.IHaskellPrelude.drop 3}”
在表达式中:genericToJSON defaultOptions{fieldLabelModifier=Data.Char.toLower.IHaskellPrelude.drop 3}
:8:55:错误:
•无法将类型“String”与“Char”匹配
所需类型:字符串->字符
实际类型:字符串->字符串
•在“(.”的第二个参数中,即“ihaskell prelude.drop 3”
在记录的“fieldLabelModifier”字段中
在“genericToJSON”的第一个参数中,即“defaultOptions{fieldLabelModifier=Data.Char.toLower.IHaskellPrelude.drop 3}”
当我尝试裸体“滴”而不是Ihaskelle Prelude滴时,我得到:
instance ToJSON R3 where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = Data.Char.toLower . drop 3 }
<interactive>:8:55: error:
Ambiguous occurrence ‘drop’
It could refer to either ‘BS.drop’, imported from ‘Data.ByteString’
or ‘IHaskellPrelude.drop’, imported from ‘Prelude’ (and originally defined in ‘GHC.List’)
or ‘T.drop’, imported from ‘Data.Text’
实例到JSON R3,其中
toJSON=genericToJSON-defaultOptions{
fieldLabelModifier=Data.Char.toLower.drop 3}
:8:55:错误:
不明确事件“下降”
它可以引用从“Data.ByteString”导入的“BS.drop”
或“IHaskellPrelude.drop”,从“Prelude”导入(最初在“GHC.List”中定义)
或“T.drop”,从“Data.Text”导入
您可以组合两个函数T.toLower
和drop 3
,但类型不匹配。事实上,如果我们查找类型,我们会看到和。字符串
是字符
的列表,但文本
不是:可以将文本
视为压缩的字符“块”
但是,我们可以组成一个类型为String->String
的函数,该字段的类型为:
在这种情况下,模板Haskell部分将实现FromJSON
和ToJSON
实例
注:我们可以使用合格的导入,以便更清楚地了解我们使用的功能,例如:
import qualified Data.List as L
import qualified Data.Char as C
instance ToJSON R3 where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = map C.toLower . L.drop 3
}
您似乎正在使用
来降低数据.Text
中的值,它与文本
一起使用,而不是与字符串
一起使用,因此很自然地,它不适合在那里使用
相反,您可以使用and将其映射到字符串上:
fieldLabelModifier = map toLower . drop 3
非常感谢。这给了我:8:35:错误:不明确的出现“toLower”
导入Data.Char的常用别名是什么?我有前奏曲,Data.Text,Data.ByteString作为BS,Data.Text.Lazy.IO作为I。六个其他字符串转换。我仍在学习,但不幸的是,我还没有发现一个问题,它不需要我导入和处理所有可能的字符串库。@Mittenchops:你可以只隐藏你的文本的toLower
,例如使用导入数据。文本隐藏(toLower)
。但这会阻止我使用它,对吗?我正在程序的其他地方使用它。@Mittenchops:您可以定义两个导入语句:导入数据。文本隐藏(toLower)
和导入限定数据。例如,文本为T
。或者只需以限定的方式导入Data.Char
。@Mittenchops:智能构造函数通常用于(a)阻止导出数据构造函数,从而阻止模块用户解包构造函数(此处仍在进行),以及(b)预处理验证,但在这里,您没有编写任何预处理或验证逻辑。因此,我们可以将makeR3
函数定义为makeR3=R3
。但我们不能使用此函数来解包数据。这似乎与我正在导入的数据。文本冲突。那么,是否将其作为限定项导入?
import Data.Char(toLower)
instance ToJSON R3 where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = map toLower . drop 3
}
{-# LANGUAGE DeriveGeneric, TemplateHaskell #-}
import Data.Char(toUpper)
import Data.Aeson.TH(deriveJSON, defaultOptions, Options(fieldLabelModifier))
data Test = Test { attribute :: String } deriving Show
$(deriveJSON defaultOptions {fieldLabelModifier = map toUpper . drop 3} ''Test)
import qualified Data.List as L
import qualified Data.Char as C
instance ToJSON R3 where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = map C.toLower . L.drop 3
}
makeR3 = R3
fieldLabelModifier = map toLower . drop 3