Json.NET根据属性类型使属性成为必需

我正在努力使用.Net核心中的自定义json序列化,我正在尝试默认所需的所有属性,除非属性具有特定类型。 这是我想要实现的一个例子:

让我们确定我有以下类型:F#:

type FooType = { id: int name: string optional: int option } 

你可以考虑下面的代码与C#中的类似:

 class FooType = { int Id {get;set;}; string Name {get;set;}; Nullable Optional {get;set;}; } 

我想要做的是返回错误,如果json对象中缺少Id或Name属性,但如果缺少Optional,则反序列化而不会出现错误(因此基本上根据需要将属性设置为不需要)。 我可以使用此示例中的RequireObjectPropertiesContractResolver标记所有属性: https : RequireObjectPropertiesContractResolver但不幸的是我无法构建更具动态性的东西。

我还有我希望添加到序列化的可选类型的默认转换器。 它不是这个特定问题的一部分,但是如果您知道如何将属性标记为必需或在一个地方使用自定义转换器,那么它甚至可能更大。

您可以将来自Json.NET的合同解析器与反序列化的所有属性结合起来,并将答案中的逻辑与Reflection一起查找属性是否为 pswg 的选项类型 ,以标记所有成员除了那些可选的成员:

 type RequireObjectPropertiesContractResolver() = inherit DefaultContractResolver() override this.CreateObjectContract(objectType : Type) = let contract = base.CreateObjectContract(objectType) contract.ItemRequired <- new System.Nullable(Required.Always); contract override this.CreateProperty(memberInfo : MemberInfo, memberSerialization : MemberSerialization) = let property = base.CreateProperty(memberInfo, memberSerialization); // https://stackoverflow.com/questions/20696262/reflection-to-find-out-if-property-is-of-option-type let isOption = property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() = typedefof> if isOption then ( property.Required <- Required.Default property.NullValueHandling <- new System.Nullable(NullValueHandling.Ignore) ) property 

然后,反序列化如下:

 let settings = new JsonSerializerSettings() settings.ContractResolver <- new RequireObjectPropertiesContractResolver() let obj = JsonConvert.DeserializeObject(inputJson, settings) 

笔记:

  • 我还添加了NullValueHandling.Ignore这样没有值的可选成员就不会被序列化。

  • 您可能希望缓存合同解析程序以获得最佳性能 。

  • Option<'T>Nullable<'T> 。 我检查了typedefof>但你可以添加一个typedefof>的检查,如果你想要:

     let isOption = property.PropertyType.IsGenericType && (property.PropertyType.GetGenericTypeDefinition() = typedefof> || property.PropertyType.GetGenericTypeDefinition() = typedefof<_>>) 

示例小提琴 ,它表明字符串{"id":101,"name":"John"}可以反序列化,但字符串{"id":101}不能。