我正在为 .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但不幸的是,我无法构建更有活力的东西。
我也有可选类型的默认转换器,我想添加到序列化中。这不是这个特定问题的一部分,但如果您知道如何标记属性是否需要以及如何在一个地方使用自定义转换器,那就更好了。
最佳答案
您可以结合 Json.NET require all properties on deserialization 中的契约(Contract)解析器使用 Reflection to find out if property is of option type 的答案中的逻辑通过 p.s.w.g标记除根据需要可选的成员之外的所有成员:
type RequireObjectPropertiesContractResolver() =
inherit DefaultContractResolver()
override __.CreateObjectContract(objectType: Type) =
let contract = base.CreateObjectContract objectType
contract.ItemRequired <- System.Nullable<Required>(Required.Always)
contract
override __.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(ContractResolver = 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}
不能。
关于c# - Json.NET 根据属性类型使属性成为必需的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48327799/