我在我的记录中使用自引用成员,如下所示:

type Payload =
    { Id: Guid }
    member x.DerivedProperty = $"Derived Property using id: {x.Id}"

NewtonSoft.Json将对此进行序列化,但在迁移到System.Text.Json后,序列化时不再包含它.

是否可以将System.Text.Json配置为包含自引用成员?

编辑:这似乎是FSharp.System.Text.Json:https://github.com/Tarmil/FSharp.SystemTextJson/issues/92的副作用

正在寻找解决方法.注意,如果我没有用FSharp.System.Text.Json序列化Payload,那么它将按预期进行序列化.

推荐答案

正如您在问题中指出的那样,无法序列化记录成员属性的已知限制为FSharp.SystemTextJsonJsonFSharpConverter,请参见102:

输出不包含成员属性.拆下选项中的转换器,它会被打印出来.

但是JsonFSharpConverter对记录类型实际上做了什么呢?事实证明,这个转换器是一个factory,它为f#记录类型制造了一个JsonRecordConverter<'T>.通过对其源代码的判断,JsonRecordConverter<'T>带来的主要优势是它总是使用其parameterized constructor构造记录.中的所有记录都需要这样做.NET Core 3.1,可能仍需要for internal records英寸.NET 5及更高版本<此外,可能还需要对内部记录中的任何字段进行正确序列化——我还没有对此进行测试[2]

由于您似乎不需要为Payload类型应用转换器,因此可以 Select 不使用JsonFSharpConverter,方法是将其封装在decorator factory中,对于要使用默认序列化的类型,CanConvert(Type)方法将返回false.

例如,您可以创建一个转换器工厂,当应用某个自定义属性时,该工厂将从FSharp.System.Text.Json中 Select :

type JsonConverterFactoryDecorator (innerConverter : JsonConverterFactory) =
    inherit JsonConverterFactory ()
    member private this.innerConverter = match innerConverter with | null -> nullArg "innerConverter" | _ -> innerConverter // Guard against null if called from c# serialization code
    override this.CanConvert(t) = innerConverter.CanConvert(t)
    override this.CreateConverter(typeToConvert, options) = innerConverter.CreateConverter(typeToConvert, options)

type OptOutJsonConverterFactoryDecorator<'T when 'T :> System.Attribute> (innerConverter : JsonConverterFactory) =
    inherit JsonConverterFactoryDecorator (innerConverter)
    override this.CanConvert(t) = base.CanConvert(t) && not (t.IsDefined(typeof<'T>, false))

type JsonFSharpConverterOptOutAttribute () =
    inherit System.Attribute()

type OptOutJsonFSharpConverter () = 
    inherit OptOutJsonConverterFactoryDecorator<JsonFSharpConverterOptOutAttribute>(JsonFSharpConverter())

然后装饰Payload,如下所示:

[<JsonFSharpConverterOptOut>]
type Payload =
    { Id: Guid }
    member x.DerivedProperty = "Derived Property using id: {x.Id}"

或者,如果您希望对所有记录 Select 退出FSharp.System.Text.Json,请定义OptOutJsonFSharpConverter,如下所示:

type OptOutJsonFSharpConverter () = 
    inherit JsonConverterFactoryDecorator(JsonFSharpConverter())
    override this.CanConvert(t) = base.CanConvert(t) && not (Microsoft.FSharp.Reflection.FSharpType.IsRecord(t, BindingFlags.Public ||| BindingFlags.NonPublic))

(您可能需要进行实验,以便为记录获取最合适的序列化,例如,您可能需要选中t.IsPublic以重新启用JsonFSharpConverter以获取内部记录.)

无论您 Select 哪个版本的OptOutJsonFSharpConverter,请按以下方式初始化您的选项:

let options = JsonSerializerOptions()
options.Converters.Add(OptOutJsonFSharpConverter ())

详见100.

参见100

Json相关问答推荐

try 将文本标记放置在条形图上的同一高度

PowerShell脚本未按预期生成预期的JSON输出

Python将Pandas转换为嵌套的JSON

Allof Indide的JSON模式之一

使用JQ合并JSON列表中的对象

419(未知状态)使用laravel处理PUT请求

递归解码嵌套列表(具有任意深度的列表列表)

VSCode 为 python 文件添加标尺,但不为 C 文件添加标尺.为什么?

使用 jq 将非统一的 json 输出转换为汇总表

如何编写 jolt 规范以将不同的对象转换为数组

SwiftUI:如何使用 0 索引数组键为 JSON 添加类型

在循环中将变量添加到 bash 数组

从 JSON 对象中删除键值对

Angular 2/Web Api - json 解析错误语法错误意外结束输入

json.decoder.JSONDecodeError:期望值:第 1 行第 1 列(字符 0)

如何使用 Swift 从 NSURLSession 获取 cookie?

在 Rails 3 中处理 JS/ERB 模板中的 JSON

Peewee 模型转 JSON

使用 JSON.NET 序列化/反序列化对象字典

Java HashMap 与 JSONObject