将字典键从json反序列化为.net中的枚举

本文关键字:net 枚举 反序列化 字典 json | 更新日期: 2023-09-27 18:07:02

我正在读取包含有关图像信息的API的json响应。
它的字典格式如下:

images: {
    low_resolution: {
        url: "...",
        width: 150,
        height: 150
    },
    high_resolution: {
        url: "...",
        width: 450,
        height: 450
    }
}

我将响应反序列化为对象,并将图像反序列化为Dictionary属性,如下所示:

[DataContract()]
public class Post
{
    ...
    [DataMember(Name = "images")]
    public IDictionary<string, Media> Images { get; set; }
    ...
}
HttpResponseMessage response = await client.GetAsync(query);
if (response.IsSuccessStatusCode)
{
    post = await response.Content.ReadAsAsync<Post>();
}
到目前为止,这一切都很好,但我宁愿将图像分辨率信息反序列化为枚举值。
因此,我创建了一个枚举ImageResolution,并将字典键从string更改为ImageResolution

只要实际的枚举值等于json字符串,这也是成功反序列化的,但是我想改变枚举值。
根据其他各种帖子,我尝试了以下内容:

[DataContract()]
public enum ImageResolution
{
    [EnumMember(Value = "low_resolution")]
    Low,
    [EnumMember(Value = "high_resolution")]
    High,
}

也从搜索我也试着添加:

[JsonConverter(typeof(StringEnumConverter))]

但是到目前为止都没有效果。
响应中还有另一个属性,我成功地反序列化为enum并使用JsonConverter属性更改enum值,但这是一个直接的属性,而不是字典键,所以我猜它是一个字典键正在引起一些问题。

是否有可能将json值反序列化为不同文本值的enum字典键?

将字典键从json反序列化为.net中的枚举

您需要为整个Dictionary编写一个CustomConverter。

我调整代码使用EnumMember而不是在另一个帖子中使用的前缀:

public class DictionaryWithSpecialEnumKeyConverter : JsonConverter
{
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException();
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var valueType = objectType.GetGenericArguments()[1];
        var intermediateDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeof(string), valueType);
        var intermediateDictionary = (IDictionary)Activator.CreateInstance(intermediateDictionaryType);
        serializer.Populate(reader, intermediateDictionary);
        var finalDictionary = (IDictionary)Activator.CreateInstance(objectType);
        foreach (DictionaryEntry pair in intermediateDictionary)
            finalDictionary.Add(ToEnum<ImageResolution>(pair.Key.ToString()), pair.Value);
        return finalDictionary;
    }
    private T ToEnum<T>(string str)
    {
        var enumType = typeof(T);
        foreach (var name in Enum.GetNames(enumType))
        {
            var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
            if (enumMemberAttribute.Value == str) return (T)Enum.Parse(enumType, name);
        }
        return default(T);
    }
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

并在字典上使用:

 [DataContract]
 public class Post
 {
    [JsonConverter(typeof(DictionaryWithSpecialEnumKeyConverter))]
    [DataMember(Name = "images")]
    public Dictionary<ImageResolution, Media> Images { get; set; }
 }