DataContractJsonSerializer忽略EnumMemberAttribute值

时间:2018-02-16 04:19:34

标签: c# .net enums datacontract datacontractjsonserializer

这是我的代码:

[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
}

我希望根据给定的字符串显示枚举值,而不是整数值。出于某种原因,值被忽略。

序列化代码没什么特别的:

protected string GetRuntimeValue(RuntimeValue value)
{
    MemoryStream ms = new MemoryStream();
    _serializer.WriteObject(ms, value);
    return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}

我去了the Microsoft documentation并找到了一个带有一些样板代码的例子,它们继承了IExtensibleDataObject(没有解释原因)。我将代码添加到我的基类,没有变化。

我做错了什么?应该简单,不是吗?

1 个答案:

答案 0 :(得分:1)

坏消息是DataContractJsonSerializer忽略了EnumMember属性,这是by design

  

枚举成员值被视为JSON中的数字,即   不同于它们在数据合同中的处理方式   包含在成员名称中。 ...如果使用,则忽略EnumMemberAttribute和NonSerializedAttribute属性。

Microsoft支持代理confirmed this并提出了一个kludge,它将公开一个用DataMember修饰的属性,以供序列化程序使用,它调用Enum.GetName()来获取字符串名称枚举值。

在你的情况下需要修改它以返回一个字符串,其中第一个字母转换为小写字母:

[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); }
    }
}

使用从here借来的扩展方法来做小写的事情:

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);
}

测试:

Console.WriteLine(GetRuntimeValue(new RuntimeValue()));

输出:

  

{"目的":" definitionTarget"}

我个人会尽可能使用JSON.NET,但为了我的答案,我假设你已经考虑过这个选项并且有充分的理由坚持使用这个序列化器。