2014-09-03 71 views
5

我想序列化一个枚举类型,以便它返回一个枚举数组作为包含“值”,“名称”和数据注释值。我需要序列化帮助。这是我到目前为止已经完成: 枚举:Json.NET带有数据注释的枚举类型的自定义序列化

public enum Status 
{ 
    [Display(Name="Active status")] 
    Active = 1, 
    [Display(Name = "Deactive status")] 
    Deactive = 2, 
    [Display(Name = "Pending status")] 
    Pending = 3 
} 

的DTO对象应连载:

public class ProjectDto 
{ 
    public Type StatusEnum { get; set; } 

    public Status CurrentStatus { get; set; } 
} 

值的勘定:

var project = new ProjectDto 
{ 
    CurrentStatus = Status.Active, 
    StatusEnum = typeof (Status) 
}; 
var output = JsonConvert.SerializeObject(project); 

为了获取值从我使用的枚举:

Enum.GetNames(typeof(Status)) //To get the names in the enum 
Enum.GetValues(typeof(Status)) //To get the values in the enum 

获取数据标注名称值是有点麻烦,但我发现这篇文章中帮助:http://geeksharp.com/2011/11/02/power-up-your-enumerations/ 他们已经创建了使用将获得的价值写在数据标注一个辅助方法:

public static string GetAttributeValue<T>(this Enum e, 
    Func<T, object> selector) where T : Attribute 
{ 
    var output = e.ToString(); 
    var member = e.GetType().GetMember(output).First(); 
    var attributes = member.GetCustomAttributes(typeof(T), false); 

    if (attributes.Length > 0) 
    { 
     var firstAttr = (T)attributes[0]; 
     var str = selector(firstAttr).ToString(); 
     output = string.IsNullOrWhiteSpace(str) ? output : str; 
    } 

    return output; 
} 

而且你可以使用这个值。

.GetAttributeValue<DisplayAttribute>(y => y.Name) 

输出应该是这样的

{ 
    statusEnum: [ 
     { "value": "1", "name": "Active", "label": "Active status" }, 
     { "value": "2", "name": "Deactive", "label": "Deactive status" }, 
     { "value": "3", "name": "Pending", "label": "Pending status" } 
    ], 
    currentStatus: { "value": "1", "name": "Active", "label": "Active status" } 
} 

如前所述我需要帮助创建自定义Json.NET序列化和反序列化来获得所需的输出。任何帮助都会被支持。

+1

“CurrentStatus”属性实际上是一个数组吗?另外,SystemEnum类型的'StatusEnum'如何被序列化为一个看起来像这样的对象呢? – 2014-09-03 11:55:53

+1

对不起。我错过了我在输出中混淆了statusEnum和currentStatus,现在已经修复。statusEnum应该代表状态枚举类型及其所有值,而currentStatus应该代表已被“选中”的单枚举值 – 2014-09-03 12:05:17

回答

7

好吧,这或许可以被清理了一下,但我会写两个自定义转换器:一个用于Enum类型,另一个用于枚举值:

我创建了一个自定义类序列化到年底结果是你想要的:

public class EnumValue 
{ 
    public int Value { get; set; } 

    public string Name { get; set; } 

    public string Label { get; set; } 
} 

除了作为一个静态类,做一些跑腿的从Enum S和枚举值创建该类型的实例:

public static class EnumHelpers 
{ 
    public static EnumValue GetEnumValue(object value, Type enumType) 
    { 
     MemberInfo member = enumType.GetMember(value.ToString())[0]; 

     DisplayAttribute attribute = 
      member.GetCustomAttribute<DisplayAttribute>(); 

     return new EnumValue 
     { 
      Value = (int)value, 
      Name = Enum.GetName(enumType, value), 
      Label = attribute.Name 
     }; 
    } 

    public static EnumValue[] GetEnumValues(Type enumType) 
    { 
     Array values = Enum.GetValues(enumType); 

     EnumValue[] result = new EnumValue[values.Length]; 

     for (int i = 0; i < values.Length; i++) 
     { 
      result[i] = GetEnumValue(
       values.GetValue(i), 
       enumType); 
     } 

     return result; 
    } 
} 

然后有两个转换器类。这第一个序列化System.Type到你想要的对象:

public class EnumTypeConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     if (value == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     EnumValue[] values = EnumHelpers.GetEnumValues((Type)value); 

     serializer.Serialize(writer, values); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override bool CanRead { get { return false; } } 

    public override bool CanConvert(Type objectType) 
    { 

     return typeof(Type).IsAssignableFrom(objectType); 
    } 
} 

然后还有序列化的实际枚举值之一:

public class EnumValueConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     if (value == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     EnumValue result = EnumHelpers.GetEnumValue(value, value.GetType()); 

     serializer.Serialize(writer, result); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override bool CanRead { get { return false; } } 

    public override bool CanConvert(Type objectType) 
    { 

     return objectType.IsEnum; 
    } 
} 

这里是你将如何使用这一切:

var pr = new ProjectDto(); 
pr.CurrentStatus = Status.Active; 
pr.StatusEnum = typeof(Status); 

var settings = new JsonSerializerSettings(); 
settings.Converters = new JsonConverter[] 
{ 
    new EnumTypeConverter(), 
    new EnumValueConverter() 
}; 
settings.Formatting = Newtonsoft.Json.Formatting.Indented; 

string serialized = JsonConvert.SerializeObject(pr, settings); 

例如:https://dotnetfiddle.net/BVp7a2

+0

感谢队友,这就是我一直在寻找的!对于为什么断线获得\ r \ n的任何建议? – 2014-09-03 13:43:09

+2

@ArneHB:你的意思是在生成的JSON或属性值?您可以通过删除“缩进”格式选项来删除换行符。 – 2014-09-03 13:45:13

+0

@AndrewWhitetaker对不起我的坏,我有点触动快乐的评论之前,我意识到我试图序列化两次。感谢您的帮助,它干净而漂亮的解决方案!我移动了转换器,所以它现在在全球JSON序列化的全球工作 – 2014-09-03 14:31:23