How to prevent Json.NET converting enum to string?

落花浮王杯 提交于 2019-12-22 09:27:45

问题


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.


回答1:


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"
}


来源:https://stackoverflow.com/questions/24985148/how-to-prevent-json-net-converting-enum-to-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!