将枚举序列化为字符串

Nao*_*aor 47 c# json datacontract

我有一个枚举:

public enum Action {
    Remove=1,
    Add=2
}
Run Code Online (Sandbox Code Playgroud)

一节课:

[DataContract]
public class Container {
    [DataMember]
    public Action Action {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

当将Container的实例序列化为json时,我得到:( {Action:1}如果Action被删除).

我想得到:( {Action:Remove}而不是int我需要ToString形式的枚举)

我可以在不增加其他成员的情况下这样做吗?

L.B*_*L.B 30

使用 Json.Net,您可以将自定义StringEnumConverter

public class MyStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is Action)
        {
            writer.WriteValue(Enum.GetName(typeof(Action),(Action)value));// or something else
            return;
        }

        base.WriteJson(writer, value, serializer);
    }
}
Run Code Online (Sandbox Code Playgroud)

并序列化为

string json=JsonConvert.SerializeObject(container,new MyStringEnumConverter());
Run Code Online (Sandbox Code Playgroud)

  • 实际上......你甚至不需要编写这个类 - 你可以传入"new Newtonsoft.Json.Converters.StringEnumConverter()" - 它具有处理所有枚举的额外好处,并且可以正确地反序列化它们同样(不知道为什么,但上面的类没有正确地反序列化枚举,即使它只是被调用的基类方法). (8认同)
  • 你可以为每个枚举做,不仅仅是你的:`if(value.GetType().IsEnum){writer.WriteValue(Enum.GetName(value.GetType(),value)); 返回; }` (3认同)

Pau*_*ner 21

使用枚举时,JSON格式化程序具有非常专业的行为; 正常的数据协定属性被忽略,它将您的枚举视为一个数字,而不是您期望与其他格式相关的更易读的字符串.虽然这使得处理标志类型的枚举变得容易,但它使得大多数其他类型更难以使用.

来自MSDN:

枚举成员值在JSON中被视为数字,这与在数据协定中处理它们的方式不同,它们作为成员名称包含在内.有关数据协定处理的更多信息,请参阅数据协定中的枚举类型.

  • 例如,如果你有public enum Color {red, green, blue, yellow, pink},序列化黄色产生数字3而不是字符串"黄色".

  • 所有枚举成员都是可序列化的.如果使用,则忽略EnumMemberAttribute和NonSerializedAttribute属性.

  • 可以反序列化不存在的枚举值 - 例如,即使没有定义相应的颜色名称,也可以将值87反序列化为先前的颜色枚举.

  • 标志枚举不是特殊的,并且与任何其他枚举一样对待.

解决此问题的唯一实用方法是允许最终用户指定字符串而不是数字,这是在合同中不使用枚举.相反,实际的答案是用字符串替换你的枚举并对值执行内部验证,以便可以将其解析为一个有效的枚举表示.

或者(虽然不是为了佯攻),你可以用自己的格式替换JSON格式化程序,它会像其他格式化程序一样尊重枚举.


GPR*_*GPR 19

您只需添加属性:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] 
Run Code Online (Sandbox Code Playgroud)

到未作为字符串序列化的枚举属性.

或者如果你有一个更奇特的格式,你可以使用下面的属性告诉JSON序列化程序只序列你已经格式化的属性.取决于你的其余实现.它还识别属性上的DataMember属性.

[JsonObject(MemberSerialization = MemberSerialization.OptOut)]
public class Container
{
    public Action Action { get; set; }

    [JsonProperty(PropertyName = "Action")]
    public string ActionString
    {
        get
        {
            return Action.ToString();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考:名称空间略有变化:`[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]` (4认同)

小智 12

这是一个简单的方法:

JsonConvert.SerializeObject(myObject, Formatting.Indented, new StringEnumConverter());
Run Code Online (Sandbox Code Playgroud)