[英]JSON.NET - custom enum handling at deserialization
我們有一個JSON,可以將其反序列化為自定義域模型,一點問題都沒有。 它包含一個作為自定義枚舉的屬性:
public enum UserType
{
President,
Chump
}
現在,我們更改了枚舉類,但仍然需要接受並反序列化到達的任何JSON的先前值。 就像我們現在有兩個版本的JSON
public enum UserType
{
President,
Vice-President,
Citizen // Chump maps to Citizen, now.
}
以及json本身。
"userType": "chump"; // needs to map to Citizen
我不確定該怎么做。
這是使用JsonConverter
嗎?
同樣,這是我們用於所有序列化和反序列化的自定義設置。 注意:我們將任何枚舉序列化為其string
描述/值,而不是其int
值。
internal static JsonSerializerSettings JsonSerializerSettings => new JsonSerializerSettings
{
Converters = new JsonConverter[]
{
new StringEnumConverter()
},
Formatting = Formatting.Indented
};
干杯!
在您的Enum
只需添加EnumMember
屬性,該屬性指定序列化/反序列化過程的值。
public enum UserType
{
President,
VicePresident,
[EnumMember(Value = "chump")]
Citizen // Chump maps to Citizen, now.
}
該物業userType
將是Citizen
的時候,在你的JSON,在userType
屬性等於"Chump"
或"Citizen"
。
請記住將System.Runtime.Serialization
引用添加到您的項目。
我注意到對EnumMember
屬性的Value
屬性的檢查區分大小寫。 因此,如果在json中有"chump"
則不能使用"Chump"
"chump"
。 要解決此問題,可以使用自定義StringEnumConverter
。
public class UserTypeEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var userTypeType = typeof(UserType);
if (objectType == userTypeType)
{
var value = reader.Value.ToString().ToLower();
foreach (var item in Enum.GetNames(userTypeType))
{
var memberValue = GetEnumMemberValue(userTypeType.GetMember(item)[0]);
if (memberValue != null && memberValue.ToLower() == value)
{
return Enum.Parse(userTypeType, item);
}
}
}
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
private static string GetEnumMemberValue(MemberInfo memberInfo)
{
var attributes = memberInfo.GetCustomAttributes(typeof(EnumMemberAttribute), inherit: false);
if (attributes.Length == 0) return null;
return ((EnumMemberAttribute)attributes[0]).Value;
}
在上面的代碼中,我僅檢查EnumMember
屬性,因為默認StringEnumConvert
已經完成了UserType
的成員不區分大小寫的檢查。
請注意,由於檢查,此轉換器僅對您的UserType
枚舉有效:
var userTypeType = typeof(UserType);
if (objectType == userTypeType)
{
將JsonSerializerSettings
初始化替換為:
internal static JsonSerializerSettings JsonSerializerSettings => new JsonSerializerSettings
{
Converters = new JsonConverter[]
{
new UserTypeEnumConverter()
},
Formatting = Formatting.Indented
};
我假設Vice-President
枚舉數是UserType
VicePresident
。
您可以實現派生自StringEnumConverter
的自定義Converter
:
public class UserTypeEnumConverter : StringEnumConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(UserType);
}
public override object ReadJson(JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
var isNullable = (Nullable.GetUnderlyingType(objectType) != null);
if (!isNullable)
{
throw new JsonSerializationException();
}
return null;
}
var token = JToken.Load(reader);
var value = token.ToString();
if (string.Equals(value, "chump", StringComparison.OrdinalIgnoreCase))
{
return UserType.Citizen;
}
else
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
}
轉換器處理基礎類型也可以為空的情況,並且僅在反序列化類上聲明的屬性的類型為UserType
時才調用該轉換器。 然后,它檢查所解析的值是否為“不贊成使用的值”,如果不是,則將讀取委托給基本StringEnumConverter
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.