如何防止Json.NET将枚举转换为字符串? [英] How to prevent Json.NET converting enum to string?

查看:142
本文介绍了如何防止Json.NET将枚举转换为字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下类

  public class RequestSections:RequestBase 
{
public RequestSections(Command c,字典< SectionIdentifier,BigInteger> v):base(c)
{
VERSIONS = v;
}

public Dictionary< SectionIdentifier,BigInteger> VERSIONS {get;组; }
}

使用JSON.NET将其序列化为JSON,并生成以下JSON输出:

  {
VERSIONS:{
照片:901,
音乐:902
},
CMD:43
}

问题是 SectionIdentifier 枚举,但JSON.NET将它们转换为字符串。

  public enum SectionIdentifier 
{
照片= 1000,
音乐
}

如何防止JSON.NET转换整数枚举值到字符串?我只想看到他们的整数表示。



顺便说一下, CMD $ c> RequestBase 类也是枚举类型,但不幸的是,它不会转换为字符串。

解决方案

JSON spec 表示属性名称(键)在对象中必须是字符串。如果您有一个使用枚举值作为键的字典,Json.Net只需在这些值上调用 Convert.ToString()来获取JSON属性名称。 (这可以在 GetPropertyName()方法中看到/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.csrel =noreferrer>源代码,由 SerializeDictionary()调用。)



可以覆盖此默认行为,以便Json.Net将将数字枚举字典键写入JSON(当然也可以符合规范)。这可以使用自定义 ContractResolver 或自定义 JsonConverter 完成。在这种情况下,解析器方法可能会更简单一些,所以我将在这里展示。以下是您需要的代码:

  class CustomResolver:DefaultContractResolver 
{
protected override JsonDictionaryContract CreateDictionaryContract(键入objectType)
{
var contract = base.CreateDictionaryContract(objectType);

var keyType = contract.DictionaryKeyType;
if(keyType.BaseType == typeof(Enum))
{
contract.PropertyNameResolver =
propName => ((int)Enum.Parse(keyType,propName))。ToString();
}

退货合同;
}
}

要序列化,将自定义解析器的一个实例传递给串行器通过这样的设置:

  JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.ContractResolver = new CustomResolver();

string json = JsonConvert.SerializeObject(foo,settings);

这是一个有创意的演示,表明它有效。您可以注释掉设置解析器以切换行为的行。

  class Program 
{
static void Main(string [] args)
{
var dict = new Dictionary< Color,string>
{
{Color.Red,#FF0000},
{Color.Green,#00FF00},
{Color.Blue,#0000FF},
{Color.White,#FFFFFF}
};

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomResolver();
settings.Formatting = Formatting.Indented;

string json = JsonConvert.SerializeObject(dict,settings);
Console.WriteLine(json);
}

枚举颜色{Red = 1,Green = 2,Blue = 3,White = 4}
}
pre>

输出:

  {
1 :#FF0000,
2:#00FF00,
3:#0000FF,
4:#FFFFFF
}


The following class

public class RequestSections : RequestBase
{
    public RequestSections(Command c, Dictionary<SectionIdentifier, BigInteger> v) : base(c)
    {
        VERSIONS = v;
    }

    public Dictionary<SectionIdentifier, BigInteger> VERSIONS { get; set; }
}

is serialized to JSON using JSON.NET and producing the following JSON output:

{
  "VERSIONS": {
    "Photos": 901,
    "Music": 902
  },
  "CMD": 43
}

The problem is that SectionIdentifier is enum but JSON.NET converts them to string.

public enum SectionIdentifier
{
    Photos = 1000,
    Music
}

How can I prevent JSON.NET converting integer enum values to string? I would like to see their integer representations only.

By the way, CMD which is residing in RequestBase class is also enum type, but somehow luckily it is not converted to string.

解决方案

The JSON spec says that property names (keys) in objects must be strings. If you have a dictionary that uses enum values as keys, Json.Net simply calls Convert.ToString() on those values to get the JSON property names. (This can be seen in the GetPropertyName() method in the source code, which is called by SerializeDictionary().)

It is possible to override this default behavior so that Json.Net will write numeric enum dictionary keys to the JSON (still as strings, of course, in keeping with the spec). This can be done using either a custom ContractResolver or a custom JsonConverter. The resolver approach will probably be a bit simpler in this particular case, so I'll show that here. Here is the code you would need:

class CustomResolver : DefaultContractResolver
{
    protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
    {
        var contract = base.CreateDictionaryContract(objectType);

        var keyType = contract.DictionaryKeyType;
        if (keyType.BaseType == typeof(Enum))
        {
            contract.PropertyNameResolver = 
                     propName => ((int)Enum.Parse(keyType, propName)).ToString();
        }

        return contract;
    }
}

To serialize, pass an instance of the custom resolver to the serializer via the settings like this:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomResolver();

string json = JsonConvert.SerializeObject(foo, settings);

Here is a contrived demo to show that it works. You can comment out the line that sets the resolver to toggle the behavior.

class Program
{
    static void Main(string[] args)
    {
        var dict = new Dictionary<Color, string>
        {
            { Color.Red, "#FF0000" },
            { Color.Green, "#00FF00" },
            { Color.Blue, "#0000FF" },
            { Color.White, "#FFFFFF" }
        };

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.ContractResolver = new CustomResolver();
        settings.Formatting = Formatting.Indented;

        string json = JsonConvert.SerializeObject(dict, settings);
        Console.WriteLine(json);
    }

    enum Color { Red = 1, Green = 2, Blue = 3, White = 4 }
}

Output:

{
  "1": "#FF0000",
  "2": "#00FF00",
  "3": "#0000FF",
  "4": "#FFFFFF"
}

这篇关于如何防止Json.NET将枚举转换为字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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