Reputation: 2032
This is my code:
[DataContract] // (Name = "Type")]
public enum Purpose
{
[EnumMember(Value = "definitionTarget")]
DefinitionTarget = 0,
[EnumMember(Value = "definitionSource")]
DefinitionSource = 1,
[EnumMember(Value = "semanticRole")]
SemanticRole = 2,
[EnumMember(Value = "dataType")]
DataType = 3
}
I want the enum values to display according to the strings given, not the integer values. For some reason, the values are ignored.
The serialization code is nothing fancy:
protected string GetRuntimeValue(RuntimeValue value)
{
MemoryStream ms = new MemoryStream();
_serializer.WriteObject(ms, value);
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
I went to the Microsoft documentation and found an example with some boilerplate code where they inherit IExtensibleDataObject (no explanation why). I added the code to my base class, no change.
What am I doing wrong? Should be something simple, no?
Upvotes: 3
Views: 4184
Reputation: 21548
The bad news is that DataContractJsonSerializer
ignores the EnumMember
attribute and this is by design:
Enumeration member values are treated as numbers in JSON, which is different from how they are treated in data contracts, where they are included as member names. ... The EnumMemberAttribute and the NonSerializedAttribute attributes are ignored if used.
A Microsoft support agent also confirmed this and suggested a kludge which is to expose a property decorated with DataMember
for the serializer to use instead, which calls Enum.GetName()
to get the string name of the enum value.
It would need to be modified in your case to return a string with the first letter converted to lower case:
[DataContract]
public class RuntimeValue
{
public Purpose Purpose { get; set; }
[DataMember(Name = "Purpose")]
string PurposeString
{
get { return Enum.GetName(typeof(Purpose), this.Purpose).FirstCharacterToLower(); }
set { this.Purpose = (Purpose)Enum.Parse(typeof(Purpose), value, true); }
}
}
Uses an extension method borrowed from here to do the lower case stuff:
public static string FirstCharacterToLower(this string str)
{
if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
return str;
return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}
Testing:
Console.WriteLine(GetRuntimeValue(new RuntimeValue()));
Output:
{"Purpose":"definitionTarget"}
Personally I would use JSON.NET instead if possible but for the sake of my answer I am assuming that you have already considered that option and have good reason to stick with this serializer.
Upvotes: 2