即使使用默认设置,Json.NET也会将枚举序列化为字符串

two*_*wer 5 c# json json.net

我正在使用Json.NET 7.0.1.

文件说,

Enum [序列化为] Integer(可以是StringEnumConverter的枚举值名称)

在我的Global.asax.cs中,我指定默认设置如下:

JsonConvert.DefaultSettings = (() =>
{
    var settings = new JsonSerializerSettings();
    settings.Converters.Add(new StringEnumConverter());
    return settings;
});
Run Code Online (Sandbox Code Playgroud)

但是,在某些情况下,我希望Enums将其序列化为整数,例如,当我构建要存储在数据库中的JSON时.

我是这样做的:

public class JsonSerializedType<T> : IUserType where T : class
{
    private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings();

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        cmd.Parameters[index].Value = JsonConvert.SerializeObject(value as T, serializerSettings);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,即使在这种情况下Enums也被序列化为字符串.我检查serializerSettings过没有Converters,它ContractResolvernull.

为什么会这样?

dbc*_*dbc 5

发生这种情况是因为通过内部调用JsonConvert.SerializeObject将传入设置应用到默认设置之上JsonSerializer.CreateDefault(JsonSerializerSettings settings)。我不知道这种行为是否/在哪里记录,但它在源代码中可见。因此,除了本地指定的转换器的空列表之外,还将使用默认的转换器列表,这意味着StringEnumConverter将使用默认值。

您有几个选项可以解决这个问题:

  1. JsonSerializer不使用默认设置的情况下构建自己

    public static class JsonExtensions
    {
        public static string SerializeObjectNoDefaultSettings(object value, Formatting formatting, JsonSerializerSettings settings)
        {
            var jsonSerializer = JsonSerializer.Create(settings);
            jsonSerializer.Formatting = formatting;
    
            StringBuilder sb = new StringBuilder(256);
            StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
            using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
            {
                jsonWriter.Formatting = jsonSerializer.Formatting;
                jsonSerializer.Serialize(jsonWriter, value);
            }
    
            return sw.ToString(); 
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后像这样使用它:

    var json = JsonExtensions.SerializeObjectNoDefaultSettings(value, Formatting.None, new JsonSerializerSettings());
    
    Run Code Online (Sandbox Code Playgroud)
  2. StringEnumConverter用一个将枚举序列化为字符串的方法取代默认值,例如:

    public class IntegerEnumConverter : StringEnumConverter
    {
        public override bool CanRead { get { return false; } }
    
        public override bool CanWrite { get { return false; } }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后像这样使用它:

    var json = JsonConvert.SerializeObject(value, Formatting.None, new JsonSerializerSettings { Converters = new JsonConverter[] { new IntegerEnumConverter() } });
    
    Run Code Online (Sandbox Code Playgroud)

    将优先选择本地指定的转换器而不是默认转换器。

暂时取消JsonConvert.DefaultSettings将是一个坏主意,因为它不是线程安全的。