有选择地使用默认的JSON转换器 [英] Selectively use default JSON converter

查看:70
本文介绍了有选择地使用默认的JSON转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Web API项目的Startup.cs中使用以下内容将Enums JSON序列化为字符串:

// Configure JSON Serialization
var jsonSerializationSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
jsonSerializationSettings.Formatting = Newtonsoft.Json.Formatting.None;
jsonSerializationSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

这是为了避免用[JsonConverter(typeof(StringEnumConverter))]

装饰每个Enum属性.

现在,如何选择某些枚举属性退出全局序列化设置,并使用默认的序列化器转换为整数?

解决方案

您可以将虚拟转换器添加到有问题的不执行任何操作的属性中:

public class NoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // Note - not called when attached directly via [JsonConverter(typeof(NoConverter))]
        throw new NotImplementedException();
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后使用 [JsonConverter(typeof(NoConverter))] 将其附加到属性.这样做之后,JsonConverter属性的转换器取代了全局指定的转换器,但是由于CanReadCanWrite都返回false,因此不执行任何转换.对于枚举的集合,可以使用 [JsonProperty(ItemConverterType = typeof(NoConverter))] .

例如,如果您定义类型:

public enum Foo { A, B, C }

public class RootObject
{
    [JsonConverter(typeof(NoConverter))]
    public Foo FooAsInteger { get; set; }

    public Foo FooAsString { get; set; }
}

然后

var root = new RootObject { FooAsInteger = Foo.B, FooAsString = Foo.B };

var json = JsonConvert.SerializeObject(root, Formatting.Indented, new StringEnumConverter());

Console.WriteLine(json);

产生输出

{
  "FooAsInteger": 1,
  "FooAsString": "B"
}

请注意,如果要将所有数据模型中所有出现的枚举都序列化为整数,也可以直接将NoConverter应用于枚举:

[JsonConverter(typeof(NoConverter))]
public enum FooAlwaysAsInteger { A, B, C }

示例小提琴.

I use the following in my Web API project's Startup.cs to JSON-serialize Enums into strings:

// Configure JSON Serialization
var jsonSerializationSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
jsonSerializationSettings.Formatting = Newtonsoft.Json.Formatting.None;
jsonSerializationSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

This is to avoid decorating every Enum property with [JsonConverter(typeof(StringEnumConverter))]

Now, how can I selectively opt out of my global serialization setting for some Enum properties and use the default serializer that converts to integers?

解决方案

You could add a dummy converter to the properties in question that does nothing:

public class NoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // Note - not called when attached directly via [JsonConverter(typeof(NoConverter))]
        throw new NotImplementedException();
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then attach it to the property using [JsonConverter(typeof(NoConverter))]. Having done so, the JsonConverter attribute's converter supersedes the globally specified converter, but since CanRead and CanWrite both return false no conversion is performed. For collections of enums, you could use [JsonProperty(ItemConverterType = typeof(NoConverter))].

For instance, if you define the types:

public enum Foo { A, B, C }

public class RootObject
{
    [JsonConverter(typeof(NoConverter))]
    public Foo FooAsInteger { get; set; }

    public Foo FooAsString { get; set; }
}

Then

var root = new RootObject { FooAsInteger = Foo.B, FooAsString = Foo.B };

var json = JsonConvert.SerializeObject(root, Formatting.Indented, new StringEnumConverter());

Console.WriteLine(json);

Produces the output

{
  "FooAsInteger": 1,
  "FooAsString": "B"
}

Note that you can also apply NoConverter directly to the enum, if you want all occurrences of the enum in all data models to be serialized as an integer:

[JsonConverter(typeof(NoConverter))]
public enum FooAlwaysAsInteger { A, B, C }

Sample fiddle.

这篇关于有选择地使用默认的JSON转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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