Reputation: 948
I have the following enum
public enum PermissionType
{
[JsonProperty(PropertyName = "can_fly")]
PermissionToFly,
[JsonProperty(PropertyName = "can_swim")]
PermissionToSwim
};
and a class with this property
[JsonProperty(PropertyName = "permissions", ItemConverterType = typeof(StringEnumConverter))]
public IList<PermissionType> PermissionKeynames { get; set; }`
I want to serialize the list of enumerations to a list of strings, and that serialize list use the string specified in PropertyName
(such as "can_swim") instead of the property's actual name "PermissionToSwim". However, whenever I call JsonConvert.SerializeObject, I end up with
"permission_keynames":["PermissionToFly","PermissionToSwim"]
instead of my desired
"permission_keynames":["can_fly","can_swim"]
I want to keep the phrase "PermissionToSwim" for use in my code, serialize to another word. Any idea how I can achieve this? My gut says that the annotation is the culprit, but I haven't been able to find the correct one.
Upvotes: 45
Views: 39072
Reputation: 51
You can define custom converter for serializing enums by JsonProperty attribute with System.Reflection.
public class EnumByAttributesConverter<TEnum> : JsonConverter<TEnum>
where TEnum : struct, Enum
{
public override void WriteJson(JsonWriter writer, TEnum value, JsonSerializer serializer)
{
var valueName = value.ToString();
var membersAttributes = GetMemberAttributePairs(value.GetType());
var propertyName = membersAttributes.FirstOrDefault(item => item.Name == valueName)
.Attribute?.PropertyName;
writer.WriteValue(propertyName ?? valueName);
}
public override TEnum ReadJson(JsonReader reader, Type objectType, TEnum existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
var name = reader.Value as string;
var membersAttributes = GetMemberAttributePairs(objectType);
var memberName = membersAttributes
.FirstOrDefault(item => item.Attribute.PropertyName == name).Name;
return Enum.TryParse<TEnum>(memberName ?? name, out var parsedResult)
? parsedResult
: default;
}
private IReadOnlyCollection<(string Name, JsonPropertyAttribute Attribute)> GetMemberAttributePairs(Type type) =>
type.GetMembers()
.Select(member => (member.Name,
Attribute: member.GetCustomAttributes(typeof(JsonPropertyAttribute), false)
.FirstOrDefault() as JsonPropertyAttribute))
.Where(p => p.Attribute != null).ToArray();
}
You still have to define JsonConverter attribute, but that way avoid to mix System.Runtime.Serialization and Newtonsoft.Json in project.
Upvotes: 1
Reputation: 126042
Looks like you can make this work using the EnumMember
attribute (found in System.Runtime.Serialization).
public enum PermissionType
{
[EnumMember(Value = "can_fly")]
PermissionToFly,
[EnumMember(Value = "can_swim")]
PermissionToSwim
}
If you use those attributes you should also not need to set the ItemConverterType
in the JsonProperty
attribute on the list.
Upvotes: 81