以下课程
public class RequestSections : RequestBase
{
public RequestSections(Command c, Dictionary<SectionIdentifier, BigInteger> v) : base(c)
{
VERSIONS = v;
}
public Dictionary<SectionIdentifier, BigInteger> VERSIONS { get; set; }
}
使用JSON.NET将序列化为JSON并生成以下JSON输出:
{
"VERSIONS": {
"Photos": 901,
"Music": 902
},
"CMD": 43
}
问题是SectionIdentifier
是enum
但JSON.NET将它们转换为字符串。
public enum SectionIdentifier
{
Photos = 1000,
Music
}
如何防止JSON.NET将整数enum
值转换为字符串?我想只看到他们的整数表示。
顺便说一句,驻留在CMD
类中的RequestBase
也是enum
类型,但幸运的是它没有转换为字符串。
答案 0 :(得分:12)
JSON spec表示对象中的属性名称(键)必须是字符串。如果您有一个使用枚举值作为键的字典,Json.Net只需在这些值上调用Convert.ToString()
即可获取JSON属性名称。 (这可以在source code的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"
}