F#: JsonConvert.SerializeObject() 多次保存同一个数据
F#: JsonConvert.SerializeObject() saves the same data multiple times
我是编程新手,F# 是我的第一语言。
我按照 in this thread 给我的建议使用 NewtonSoft.Json。以下是我的代码的一些相关部分:
[<CLIMutable>]
[<JsonObject(MemberSerialization=MemberSerialization.OptOut)>]
type FighterSummary =
{
mutable fighter: string;
mutable record: string option;
mutable reach: float option;
mutable stance: string option;
}
let fighterFilesDir = @"G:\Fighter Pages"
let fighterFiles = Directory.GetFiles(fighterFilesDir)
let fighterGroups = splitArrayIntoGroups fighterFiles 50
for group in fighterGroups do
let fighterStats = seq {
for file in group do
let html = File.ReadAllText(file)
let fighterOverview = getFighterSummary html
printfn "Extracted %s's overview." (Path.GetFileNameWithoutExtension(file))
yield fighterOverview
}
|> Seq.toArray
let fileName = Path.GetFileNameWithoutExtension(group.[0]) + " -- " + Path.GetFileNameWithoutExtension(group.[group.Count() - 1])
let saveFilePath = @"G:\Fighter Data JSON Files\" + fileName + ".json"
File.WriteAllText(saveFilePath, JsonConvert.SerializeObject(fighterStats))
我已经使用 F# Interactive 测试了函数 getFighterSummary 和 splitArrayIntoGroups。他们工作出色。
当我将 FighterSummary 类型的记录保存到 JSON 时,对于每个不同的战斗机,我都会看到类似这样的内容:
{"fighter@": "Alessio Sakara",
"record@": {
"Case": "Some",
"Fields": ["19-11-0 (1 NC)"]
},
"reach@": {
"Case": "Some",
"Fields": [182.88]
},
"stance@": {
"Case": "Some",
"Fields": ["Orthodox"]
},
"fighter": "Alessio Sakara",
"record": {
"Case": "Some",
"Fields": ["19-11-0 (1 NC)"]
},
"reach": {
"Case": "Some",
"Fields": [182.88]
},
"stance": {
"Case": "Some",
"Fields": ["Orthodox"]}
每个战士的信息都保存了两次 -- 第一次在每个字段名称的末尾带有“@”,第二次没有。
我想要的是关于战斗机的信息只保存一次,每个字段名称末尾没有“@”。
我已阅读答案 here,以回答遇到类似问题的人发布的问题。我已经尝试实施那里提供的建议,但没有奏效。
如果有人能帮助我解决这个问题,我将不胜感激。谢谢。
编辑:
我在反序列化 JSON 时也遇到了问题。当我运行
JsonConvert.DeserializeObject<FighterSummary>(File.ReadAllText(@"G:\Fighter Data JSON Files\Fighters.json"))
我收到以下错误消息:
System.Reflection.CustomAttributeFormatException:
'MemberSerialization' property specified was not found. --->
System.Reflection.CustomAttributeFormatException:
'MemberSerialization' property specified was not found.
请注意,在您提到的 post 中,他们使用 [<CliMutable>]
但成员本身不是 mutable
。在查看您的代码时,我不明白为什么您需要 mutable
(在 F# 中)。 mutable
关键字允许使用 <-
赋值,这在 F# 中很少使用。 [<CliMutable>]
在那里,因此 编译代码 是可变的,但它在 F# 代码中保持不变。
这有时在您想使用记录时很有用,例如使用反射。 JSON.Net 应该能够处理事情,如果你只是 [<CliMutable>]
而不是在 F# 中创建 mutable
关键字。
我是编程新手,F# 是我的第一语言。
我按照 in this thread 给我的建议使用 NewtonSoft.Json。以下是我的代码的一些相关部分:
[<CLIMutable>]
[<JsonObject(MemberSerialization=MemberSerialization.OptOut)>]
type FighterSummary =
{
mutable fighter: string;
mutable record: string option;
mutable reach: float option;
mutable stance: string option;
}
let fighterFilesDir = @"G:\Fighter Pages"
let fighterFiles = Directory.GetFiles(fighterFilesDir)
let fighterGroups = splitArrayIntoGroups fighterFiles 50
for group in fighterGroups do
let fighterStats = seq {
for file in group do
let html = File.ReadAllText(file)
let fighterOverview = getFighterSummary html
printfn "Extracted %s's overview." (Path.GetFileNameWithoutExtension(file))
yield fighterOverview
}
|> Seq.toArray
let fileName = Path.GetFileNameWithoutExtension(group.[0]) + " -- " + Path.GetFileNameWithoutExtension(group.[group.Count() - 1])
let saveFilePath = @"G:\Fighter Data JSON Files\" + fileName + ".json"
File.WriteAllText(saveFilePath, JsonConvert.SerializeObject(fighterStats))
我已经使用 F# Interactive 测试了函数 getFighterSummary 和 splitArrayIntoGroups。他们工作出色。
当我将 FighterSummary 类型的记录保存到 JSON 时,对于每个不同的战斗机,我都会看到类似这样的内容:
{"fighter@": "Alessio Sakara",
"record@": {
"Case": "Some",
"Fields": ["19-11-0 (1 NC)"]
},
"reach@": {
"Case": "Some",
"Fields": [182.88]
},
"stance@": {
"Case": "Some",
"Fields": ["Orthodox"]
},
"fighter": "Alessio Sakara",
"record": {
"Case": "Some",
"Fields": ["19-11-0 (1 NC)"]
},
"reach": {
"Case": "Some",
"Fields": [182.88]
},
"stance": {
"Case": "Some",
"Fields": ["Orthodox"]}
每个战士的信息都保存了两次 -- 第一次在每个字段名称的末尾带有“@”,第二次没有。
我想要的是关于战斗机的信息只保存一次,每个字段名称末尾没有“@”。
我已阅读答案 here,以回答遇到类似问题的人发布的问题。我已经尝试实施那里提供的建议,但没有奏效。
如果有人能帮助我解决这个问题,我将不胜感激。谢谢。
编辑:
我在反序列化 JSON 时也遇到了问题。当我运行
JsonConvert.DeserializeObject<FighterSummary>(File.ReadAllText(@"G:\Fighter Data JSON Files\Fighters.json"))
我收到以下错误消息:
System.Reflection.CustomAttributeFormatException: 'MemberSerialization' property specified was not found. ---> System.Reflection.CustomAttributeFormatException: 'MemberSerialization' property specified was not found.
请注意,在您提到的 post 中,他们使用 [<CliMutable>]
但成员本身不是 mutable
。在查看您的代码时,我不明白为什么您需要 mutable
(在 F# 中)。 mutable
关键字允许使用 <-
赋值,这在 F# 中很少使用。 [<CliMutable>]
在那里,因此 编译代码 是可变的,但它在 F# 代码中保持不变。
这有时在您想使用记录时很有用,例如使用反射。 JSON.Net 应该能够处理事情,如果你只是 [<CliMutable>]
而不是在 F# 中创建 mutable
关键字。