Json.NET根据属性类型使属性成为必需 [英] Json.NET make property required based on property type

查看:46
本文介绍了Json.NET根据属性类型使属性成为必需的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为.Net核心中的自定义json序列化而苦苦挣扎,除非属性具有特定类型,否则我将尝试使默认情况下所需的所有属性成为可能.这是我要实现的目标的一个示例:

I'm struggling with custom json serialization in .Net core, I'm trying to make all properties required by default except if property has specific type. Here is an example of what I'm trying to achieve:

假设我具有以下类型: F#:

Let's assument that I have following type: F#:

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

您可以考虑以下代码,类似于C#中的以下代码:

you can think about below code as similar to following in C#:

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

我想做的是如果json对象中缺少Id或Name属性,则返回错误,但是如果缺少Optional,则反序列化而不会出现错误(因此基本上将Property设置为必填项,或者不基于其类型设置).我可以通过使用此示例中的RequireObjectPropertiesContractResolver来标记所需的所有属性: https://stackoverflow.com/a/29660550,但不幸的是,我无法构建更动态的东西.

What I'm trying to do is to return error if Id or Name property is missing in json object but deserialize without error if Optional is missing (so basically to set Property as required or not based on it's type). I'm able to mark all properties as required by using RequireObjectPropertiesContractResolver from this sample: https://stackoverflow.com/a/29660550 but unfortunately I wasn't able to build something more dynamic.

我还有要添加到序列化中的可选类型的默认转换器.这不是这个特定问题的一部分,但是,如果您有一个想法,即如何标记属性是否必需,以及如何在一个位置使用自定义Converter,那会更大.

I have also default converter for Optional types I would like to add to serialization. It's not part of this one specific question but if you have an idea how to mark property to be required or not and to use custom Converter in one place than it would be even greater.

推荐答案

您可以从 Json.NET组合合同解析器要求反序列化上的所有属性 ,并具有 Reflection的答案中的逻辑,以找出属性是否为选项类型 (由 pswg 标记)来标记所有成员,但根据需要可选的成员除外:

You can combine the contract resolver from Json.NET require all properties on deserialization with the logic from the answer to Reflection to find out if property is of option type by p.s.w.g to mark all members except those that are optional as required:

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,以使没有值的可选成员不会被序列化.

  • I also added NullValueHandling.Ignore so that optional members with no value would not get serialized.

您可能想要缓存合同解析器以获得最佳性能.

Option<'T>Nullable<'T>不同.我检查了typedefof<Option<_>>,但如果需要,您也可以添加typedefof<System.Nullable<_>>的支票:

Option<'T> is not the same as Nullable<'T>. I checked for typedefof<Option<_>> but you could add a check for typedefof<System.Nullable<_>> as well if you want:

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

样本小提琴,它表明字符串{"id":101,"name":"John"}可以反序列化,但是字符串{"id":101}不能.

Sample fiddle, which demonstrates that the string {"id":101,"name":"John"} can be deserialized, but the string {"id":101} cannot.

这篇关于Json.NET根据属性类型使属性成为必需的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆