I am reading a json response from an API which contains information about images.
It is in a dictionary format like so:
images: {
low_resolution: {
url: "...",
width: 150,
height: 150
},
high_resolution: {
url: "...",
width: 450,
height: 450
}
}
I am deserializing the response into an object, and the images into a Dictionary property like so:
[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>();
}
This all works fine so far, but I'd rather deserialize the image resolution information into an enumeration value.
So I created an enumeration ImageResolution
and changed the dictionary key from string
to ImageResolution
.
This also deserializes successfully, as long as the actual enumeration value equals the json string, but I want to change the enum values.
As per various other posts, I have tried the following:
[DataContract()]
public enum ImageResolution
{
[EnumMember(Value = "low_resolution")]
Low,
[EnumMember(Value = "high_resolution")]
High,
}
Also from searching I have also tried adding:
[JsonConverter(typeof(StringEnumConverter))]
But nothing so far has worked.
There is another property in the response which I am successfully deserializing to an enum and changing the enum value using the JsonConverter
attribute, but this is a straight forward property and not a dictionary key, so I am guessing that it being a dictionary key is causing some issues.
Is it possible to deserialize the json value to an enum dictionary key of different text value?
You need to write a CustomConverter for the whole Dictionary as indicated here.
I adapted the code to use EnumMember instead of the prefix used in the other post:
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;
}
}
And use it on the Dictionary:
[DataContract]
public class Post
{
[JsonConverter(typeof(DictionaryWithSpecialEnumKeyConverter))]
[DataMember(Name = "images")]
public Dictionary<ImageResolution, Media> Images { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With