我正在努力使用.Net核心中的自定义json序列化,我正在尝试默认所需的所有属性,除非属性具有特定类型。这是我想要实现的一个例子:
让我们确定我有以下类型: F#:
type FooType = {
id: int
name: string
optional: int option
}
你可以考虑下面的代码与C#中的跟随类似:
class FooType =
{
int Id {get;set;};
string Name {get;set;};
Nullable<int> Optional {get;set;};
}
我想要做的是返回错误,如果json对象中缺少Id或Name属性,但如果缺少Optional,则反序列化而不会出错(因此基本上根据需要将属性设置为不需要)。我可以使用此示例中的RequireObjectPropertiesContractResolver
标记所有属性:https://stackoverflow.com/a/29660550但遗憾的是我无法构建更具动态性的内容。
我还有我希望添加到序列化的可选类型的默认转换器。它不是这个特定问题的一部分,但是如果你知道如何标记属性是否需要,并且在一个地方使用自定义转换器比它更大。
答案 0 :(得分:4)
您可以将Json.NET require all properties on deserialization的合同解析程序与Reflection to find out if property is of option type的答案中的逻辑p.s.w.g结合起来,以标记除了根据需要可选的成员之外的所有成员:
type RequireObjectPropertiesContractResolver() =
inherit DefaultContractResolver()
override this.CreateObjectContract(objectType : Type) =
let contract = base.CreateObjectContract(objectType)
contract.ItemRequired <- new System.Nullable<Required>(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<Option<_>>
if isOption then (
property.Required <- Required.Default
property.NullValueHandling <- new System.Nullable<NullValueHandling>(NullValueHandling.Ignore)
)
property
然后,按如下方式反序列化:
let settings = new JsonSerializerSettings()
settings.ContractResolver <- new RequireObjectPropertiesContractResolver()
let obj = JsonConvert.DeserializeObject<FooType>(inputJson, settings)
注意:
我还添加了NullValueHandling.Ignore
,以便不会将没有值的可选成员序列化。
Option<'T>
与Nullable<'T>
不同。我检查了typedefof<Option<_>>
,但如果您愿意,还可以添加typedefof<System.Nullable<_>>
支票:
let isOption = property.PropertyType.IsGenericType && (property.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>> || property.PropertyType.GetGenericTypeDefinition() = typedefof<System.Nullable<_>>)
示例fiddle,它表明字符串{"id":101,"name":"John"}
可以反序列化,但字符串{"id":101}
不能反序列化。