有什么方法可以让 JsonConvert.SerializeObject 忽略属性上的 JsonConverter 属性?

问题描述 投票:0回答:5

我有一个无法更改的课程:

public enum MyEnum {
    Item1 = 0,
    Item2 = 1
}
public class foo {
    [JsonConverter(typeof(StringEnumConverter))]
    public MyEnum EnumTypes {get; set; }
}

在该行的某个地方

JsonConvert.SerializeObject
序列化对象,并且由于
JsonConverter
属性,它会输出
foo.EnumTypes
的枚举值的名称而不是数字。

是否有办法让

JsonConvert.SerializeObject
忽略
EnumTypes
属性上的属性?

c# serialization json.net
5个回答
12
投票

这是可能的,但过程有点复杂。

基本思想是创建一个自定义

ContractResolver
并重写其
CreateProperty
方法。 像这样:

internal sealed class MyContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty( MemberInfo member, MemberSerialization memberSerialization )
    {
        var property = base.CreateProperty( member, memberSerialization );

        if( member.DeclaringType == typeof( foo ) && property.PropertyType == typeof( MyEnum ) )
        {
            property.Converter = null;
        }

        return property;
    }
}

您还需要实际实例化此类并将其传递到序列化器/反序列化器中。 它看起来是什么样子取决于你如何进行序列化,所以我不能保证如何使用它的相关示例。

如果您只是使用静态

SerializeObject
方法:

JsonConvert.SerializeObject( valueToSerialize, new SerializerSettings { ContractResolver = new MyContractResolver() } );

2
投票

之前的评论看起来确实很有希望,但由于某种原因它对我不起作用。我修改了接受的答案以满足我的需要。如果有人需要的话,这是代码

public class IgnoreConvertersContractResolver : DefaultContractResolver
{
    private readonly Type[] _typesToIgnore;

    public IgnoreConvertersContractResolver(params Type[] typesToIgnore)
    {
        _typesToIgnore = typesToIgnore;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var attributes = property.AttributeProvider.GetAttributes(false);

        foreach (var attribute in attributes)
        {
            if (attribute is JsonConverterAttribute converterAttribute 
                && _typesToIgnore.Contains(converterAttribute.ConverterType))
            {
                property.Converter = null;
                break;
            }
        }

        return property;
    }

1
投票

凯尔的回答是一个很好的起点。在这个具体的简单例子中,它工作得很好。但对我来说,它无法递归地用于嵌套属性,至少在 newtonsoft.json v12.0.3 中是这样。查看我发现的 DefaultContractResolver 中还有哪些内容可以被覆盖

public virtual JsonContract ResolveContract(Type type);

对于嵌套属性来说效果很好:

    internal sealed class NumericEnumContractResolver : DefaultContractResolver
    {
        private Type _stringEnumConverterType = typeof(StringEnumConverter);

        protected override JsonConverter ResolveContractConverter(Type objectType)
        {
            var converter = base.ResolveContractConverter(objectType);

            if ((converter != null) &&
                (converter.GetType() == _stringEnumConverterType))
            {
                converter = null;
            }

            return converter;
        }
    }

和示例用法:

JsonConvert.SerializeObject(
    myObject,
    new SerializerSettings
    {
        ContractResolver = new NumericEnumContractResolver()
    });

1
投票

我是一个简单的人,我会创建单独的 DTO,将数据复制到该对象中并序列化此 DTO 而不是原始对象。


1
投票

您可以使用 JsonIgnore 属性

public class Object
{
    public string Key { get; set; }

    [JsonIgnore]
    public string Value { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.