如何防止Json.NET将枚举转换为字符串

本文关键字:转换 字符串 枚举 何防止 Json NET | 更新日期: 2023-09-27 18:15:20

下面的class

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

使用JSON序列化为JSON。. NET并产生以下JSON输出:

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

问题是SectionIdentifierenum,但JSON。NET将它们转换为字符串。

public enum SectionIdentifier
{
    Photos = 1000,
    Music
}

如何阻止JSON。. NET将整数enum值转换为字符串?我只希望看到它们的整数表示。

顺便说一下,CMD是居住在RequestBase类也是enum类型,但不知何故幸运的是,它没有转换为字符串。

如何防止Json.NET将枚举转换为字符串

JSON规范规定对象中的属性名(键)必须是字符串。如果你有一个使用枚举值作为键的字典,Json。Net只是对这些值调用Convert.ToString()来获取JSON属性名。(这可以在源代码中的GetPropertyName()方法中看到,该方法由SerializeDictionary()调用。)

可以重写此默认行为,以便Json。Net将把数字枚举字典键写入JSON(当然,为了与规范保持一致,仍然是字符串)。这可以使用自定义ContractResolver或自定义JsonConverter来完成。在这种特殊情况下,解析器方法可能会简单一些,因此我将在这里展示它。下面是您需要的代码:

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

要序列化,通过如下设置将自定义解析器的实例传递给序列化器:

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);
    }
    enum Color { Red = 1, Green = 2, Blue = 3, White = 4 }
}
输出:

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