如何在Json.NET中使用JsonSerializerSettings在属性中指定时禁用TypeNameHandling?

时间:2017-10-25 07:00:17

标签: c# json json.net

有时我需要通过Json.NET抑制"$type"属性的输出,即使由JsonPropertyAttribute.ItemTypeNameHandling指定也是如此。怎么办呢?

我的根类如下所示:

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

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

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,但我无法找到办法。 我尝试使用TypeNameHandling.None设置JsonSerializerSettings作为jsonconvert的输入,当我不想使用下面的代码"$type"属性时:

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);
}

然后按如下方式使用它:

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

var x = CustomJsonConvert.SerializeObject(res);

我想要的JSON是:

  

{ “扩展”:[{ “的立即”:3 “URL”: “ewwer”}]}

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

  

{ “扩展”:[{ “$类型”:“DicomtoJsonConverter.IntegerExtension,   DicomtoJsonConverter”, “的立即”:3 “URL”: “ewwer”}]}

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

1 个答案:

答案 0 :(得分:1)

即使由custom ContractResolverJsonPropertyAttribute.TypeNameHandlingJsonPropertyAttribute.ItemTypeNameHandling指定,您也可以使用JsonContainerAttribute.ItemTypeNameHandling来抑制类型信息的输出。首先,定义以下合同解析程序:

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);
    }
}

如果您使用的版本早于9.0.1的Json.NET,则需要继承CamelCasePropertyNamesContractResolver而不是继承DefaultContractResolver,因为该版本中引入了NamingStrategy