我正在使用Json.NET 7.0.1。
Enum
[序列化为] Integer(可以是StringEnumConverter的枚举值名称)
在我的Global.asax.cs中,我指定默认设置如下:
JsonConvert.DefaultSettings = (() =>
{
var settings = new JsonSerializerSettings();
settings.Converters.Add(new StringEnumConverter());
return settings;
});
但是,在某些情况下,我希望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);
}
}
但是,即使在这种情况下,Enums
也会被序列化为字符串。我检查了serializerSettings
没有Converters
且其ContractResolver
是null
。
为什么会这样?
答案 0 :(得分:4)
这种情况正在发生,因为JsonConvert.SerializeObject
通过内部呼叫JsonSerializer.CreateDefault(JsonSerializerSettings settings)
将传入设置应用于默认设置之上。我不知道此行为是否/记录在哪里,但在source code中可见。因此,除本地指定转换器的空列表外,还将使用的默认转换器列表,这意味着将使用默认的StringEnumConverter
。
您可以通过以下几种方式解决此问题:
Construct the JsonSerializer
yourself未使用默认设置:
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();
}
}
然后使用它:
var json = JsonExtensions.SerializeObjectNoDefaultSettings(value, Formatting.None, new JsonSerializerSettings());
取代默认StringEnumConverter
,其中不将枚举序列化为字符串,例如:
public class IntegerEnumConverter : StringEnumConverter
{
public override bool CanRead { get { return false; } }
public override bool CanWrite { get { return false; } }
}
然后使用它:
var json = JsonConvert.SerializeObject(value, Formatting.None, new JsonSerializerSettings { Converters = new JsonConverter[] { new IntegerEnumConverter() } });
将优先选择本地指定的转换器,而不是默认转换器。
暂时清空JsonConvert.DefaultSettings
会是一个坏主意,因为它不是线程安全的。
答案 1 :(得分:2)
我们在这里看到的行为是设计的,JsonConvert
方法中的传递设置正在与提供的DefaultSettings
合并,这里是来自JsonSerializer类的Json.Net源代码的一小部分,以揭开情境的神秘面纱
private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
{
if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
{
// insert settings converters at the beginning so they take precedence
// if user wants to remove one of the default converters they will have to do it manually
for (int i = 0; i < settings.Converters.Count; i++)
{
serializer.Converters.Insert(i, settings.Converters[i]);
}
}
我们可以看到转换器与提供的默认转换器合并,虽然具有更高的优先级。
我们可以利用最近合并的转换器的更高优先级,并阻止StringEnumConverter
转换。
class PreventStringEnumConverter : StringEnumConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var type = value.GetType();
var undertype = Enum.GetUnderlyingType(type);
var converted=Convert.ChangeType(value, undertype);
writer.WriteValue(converted);
}
}
,用法如下:
var json = JsonConvert.SerializeObject(obj,
new JsonSerializerSettings
{
Converters = new List<JsonConverter> {new PreventStringEnumConverter()}
});