正如您在问题中指出的那样,无法序列化记录成员属性的已知限制为FSharp.SystemTextJson
到JsonFSharpConverter
,请参见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