通过使用Json.NET中的JsonSerializerSettings在属性中指定时如何禁用TypeNameHandling? [英] How to disable TypeNameHandling when specified in attributes by using JsonSerializerSettings in Json.NET?

查看:299
本文介绍了通过使用Json.NET中的JsonSerializerSettings在属性中指定时如何禁用TypeNameHandling?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时,即使由

Sometimes I need to suppress output of "$type" properties by Json.NET even when specified by JsonPropertyAttribute.ItemTypeNameHandling. How can this be done?

我的根类如下:

public class DomainResource
{
    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
    public List<Extension> Extensions { get; set; }
}

此外,我还有Extension的类层次结构,如下所示:

And in addition I have a class hierarchy for Extension such as the following:

public class Extension
{
    readonly string url;

    public string Url { get { return url; } }

    public Extension(string url)
    {
        this.url = url;
    }
}

public class IntegerExtension : Extension
{
    public IntegerExtension(string url) : base(url) { }

    [JsonProperty("ValueInteger")]
    public int Value { get; set; }
}

在序列化过程中的某些情况下,我想忽略ItemTypeNameHandling,但是我找不到解决方法. 当我不想要使用以下代码的"$type"属性时,我尝试使用TypeNameHandling.None作为JsonConvert的输入来设置JsonSerializerSettings.

I want to ignore ItemTypeNameHandling in certain scenarios during serialization, but I am not able to find a way to do that. I tried setting JsonSerializerSettings with TypeNameHandling.None as input for jsonconvert when I do not want "$type" properties using the code below:

public static string SerializeObject(object value)
{
    JsonSerializerSettings jsonSettings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        NullValueHandling = NullValueHandling.Ignore,
        TypeNameHandling = TypeNameHandling.None,

    };
    jsonSettings.Converters.Add(new StringEnumConverter
    {
        CamelCaseText = true
    });
    return JsonConvert.SerializeObject(value, Formatting.None, jsonSettings);
}

然后按如下所示使用它:

And then use it as follows:

var res = new DomainResource();
res.Extensions = new List<Extension>();
res.Extensions.Add(new IntegerExtension("ewwer"){Value = 3});

var x = CustomJsonConvert.SerializeObject(res);

我想要的JSON是:

{扩展名":[{"valueInteger":3,"url":"ewwer"}]}

{"extensions":[{"valueInteger":3,"url":"ewwer"}]}

但是它包含如下所示的"$type"属性:

But instead it contains "$type" properties as shown below:

{"extensions":[{"$ type":"DicomtoJsonConverter.IntegerExtension, DicomtoJsonConverter," valueInteger:3," url:" ewwer}]}

{"extensions":[{"$type":"DicomtoJsonConverter.IntegerExtension, DicomtoJsonConverter","valueInteger":3,"url":"ewwer"}]}

如何在不更改DomainResource类的情况下抑制"$type"属性的输出?

How can I suppress output of "$type" properties without changing DomainResource class?

推荐答案

您可以使用自定义ContractResolver 来抑制类型信息的输出,即使由 JsonPropertyAttribute.TypeNameHandling JsonPropertyAttribute.ItemTypeNameHandling JsonContainerAttribute.ItemTypeNameHandling .首先,定义以下合同解析器:

You can use a custom ContractResolver to suppress output of type information even when specified by JsonPropertyAttribute.TypeNameHandling, JsonPropertyAttribute.ItemTypeNameHandling or JsonContainerAttribute.ItemTypeNameHandling. First, define the following contract resolver:

public class NoTypeNameHandlingContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        // Suppress JsonPropertyAttribute.TypeNameHandling
        property.TypeNameHandling = null;
        // Suppress JsonPropertyAttribute.ItemTypeNameHandling
        property.ItemTypeNameHandling = null;
        return property;
    }

    protected override JsonContract CreateContract(Type objectType)
    {
        var contract = base.CreateContract(objectType);
        if (contract is JsonContainerContract)
        {
            // Suppress JsonContainerAttribute.ItemTypeNameHandling
            ((JsonContainerContract)contract).ItemTypeNameHandling = null;
        }
        return contract;
    }
}

然后,如下修改CustomJsonConvert.SerializeObject():

public static class CustomJsonConvert
{
    // You may want to cache the contract resolver for best performance, see
    // https://stackoverflow.com/questions/33557737/does-json-net-cache-types-serialization-information
    static readonly JsonSerializerSettings jsonSettings;
    static CustomJsonConvert()
    {
        jsonSettings = new JsonSerializerSettings
        {
            ContractResolver = new NoTypeNameHandlingContractResolver
            {
                NamingStrategy = new CamelCaseNamingStrategy
                {
                    // These are the settings used by CamelCasePropertyNamesContractResolver by default.
                    // Change them if this is not what you want.
                    OverrideSpecifiedNames = true,
                    ProcessDictionaryKeys = true,
                },
            },
            NullValueHandling = NullValueHandling.Ignore,
            TypeNameHandling = TypeNameHandling.None,
            Converters = { new StringEnumConverter { CamelCaseText = true } },
        };
    }

    public static string SerializeObject(object value)
    {
        return JsonConvert.SerializeObject(value, Formatting.None, jsonSettings);
    }
}

如果您使用的Json.NET版本早于 9.0 .1 您需要将CamelCasePropertyNamesContractResolver子类化,而不是将DefaultContractResolver子类化,因为

If you are using a version of Json.NET that predates 9.0.1 you will need to subclass CamelCasePropertyNamesContractResolver rather than subclassing DefaultContractResolver since NamingStrategy was introduced in that release.

这篇关于通过使用Json.NET中的JsonSerializerSettings在属性中指定时如何禁用TypeNameHandling?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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