枚举的JSON序列化为string

我有一个包含enum属性的类,并在使用JavaScriptSerializer序列化对象时,我的json结果包含枚举的整数值而不是其string “name”。 有没有办法让我的JSON中的string枚举,而不必创build一个自定义JavaScriptConverter ? 也许有一个属性,我可以装饰的枚举定义,或对象的财产,与?

举个例子:

 enum Gender { Male, Female } class Person { int Age { get; set; } Gender Gender { get; set; } } 

期望的json结果:

 { "Age": 35, "Gender": "Male" } 

不,没有特殊的属性可以使用。 JavaScriptSerializerenums序列化为它们的数字值,而不是它们的string表示forms。 您将需要使用自定义序列化序列化enum作为它的名称而不是数字值。

编辑:正如@OmerBakhari指出,JSON.net涵盖了这个用例(通过属性[JsonConverter(typeof(StringEnumConverter))]和其他许多不由内置的.net序列化器处理。 这里是比较序列化器的特征和function的链接 。

我发现Json.NET提供了我正在寻找一个StringEnumConverter属性的确切function:

 using Newtonsoft.Json; using Newtonsoft.Json.Converters; [JsonConverter(typeof(StringEnumConverter))] public Gender Gender { get; set; } 

有关StringEnumConverter文档的更多详细信息。

将以下代码添加到您的global.asax中,作为string的C#枚举的JSON序列化

  HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (new Newtonsoft.Json.Converters.StringEnumConverter()); 

@Iggy答案将C#枚举的JSON序列化设置为仅适用于ASP.NET(Web API等)的string。

但是为了使它也可以在ad hoc序列化中使用,请将以下内容添加到启动类(如Global.asax Application_Start)

 //convert Enums to Strings (instead of Integer) globally JsonConvert.DefaultSettings = (() => { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter { CamelCaseText = true }); return settings; }); 

有关Json.NET页面的更多信息

此外,要让你的枚举成员序列化/从特定的文本反序列化,使用

System.Runtime.Serialization.EnumMember

属性,如下所示:

 public enum time_zone_enum { [EnumMember(Value = "Europe/London")] EuropeLondon, [EnumMember(Value = "US/Alaska")] USAlaska } 

通过在Gender属性中添加一个ScriptIgnore属性,使其不被序列化,并添加一个ScriptIgnore属性,该属性被序列化:

 class Person { int Age { get; set; } [ScriptIgnore] Gender Gender { get; set; } string GenderString { get { return Gender.ToString(); } } } 

我不能像@ob。的顶部答案那样更改源模型,而且我也不想像@Iggy那样在全局范围内进行注册。 所以我结合https://stackoverflow.com/a/2870420/237091和@ Iggy的https://stackoverflow.com/a/18152942/237091允许在SerializeObject命令本身设置stringenum转换器:;

 Newtonsoft.Json.JsonConvert.SerializeObject( objectToSerialize, Newtonsoft.Json.Formatting.None, new Newtonsoft.Json.JsonSerializerSettings() { Converters = new List<Newtonsoft.Json.JsonConverter> { new Newtonsoft.Json.Converters.StringEnumConverter() } }) 

斯蒂芬的答案的这个版本不改变在JSON的名字:

 [DataContract( Namespace = "http://schemas.datacontract.org/2004/07/Whatever")] class Person { [DataMember] int Age { get; set; } Gender Gender { get; set; } [DataMember(Name = "Gender")] string GenderString { get { return this.Gender.ToString(); } set { Gender g; this.Gender = Enum.TryParse(value, true, out g) ? g : Gender.Male; } } } 

这是newtonsoft.json的答案

 enum Gender { Male, Female } class Person { int Age { get; set; } [JsonConverter(typeof(StringEnumConverter))] Gender Gender { get; set; } } 

这是一个简单的解决scheme,它将服务器端C#枚举序列化为JSON,并使用结果填充客户端的<select>元素。 这适用于简单的枚举和位标记枚举。

我已经包含了端到端的解决scheme,因为我认为大多数人想要将C#枚举序列化为JSON也可能会使用它来填充<select>下拉列表。

开始:

示例枚举

 public enum Role { None = Permission.None, Guest = Permission.Browse, Reader = Permission.Browse| Permission.Help , Manager = Permission.Browse | Permission.Help | Permission.Customise } 

一个复杂的枚举,使用按位或生成一个权限系统。 所以你不能依赖简单的索引[0,1,2 ..]作为枚举的整数值。

服务器端 – C#

 Get["/roles"] = _ => { var type = typeof(Role); var data = Enum .GetNames(type) .Select(name => new { Id = (int)Enum.Parse(type, name), Name = name }) .ToArray(); return Response.AsJson(data); }; 

上面的代码使用NancyFX框架来处理Get请求。 它使用Nancy的Response.AsJson()辅助方法 – 但不用担心,你可以使用任何标准的JSON格式化程序,因为枚举已经被投影到一个简单的匿名types中,以便序列化。

生成的JSON

 [ {"Id":0,"Name":"None"}, {"Id":2097155,"Name":"Guest"}, {"Id":2916367,"Name":"Reader"}, {"Id":4186095,"Name":"Manager"} ] 

客户端 – CoffeeScript

 fillSelect=(id, url, selectedValue=0)-> $select = $ id $option = (item)-> $ "<option/>", { value:"#{item.Id}" html:"#{item.Name}" selected:"selected" if item.Id is selectedValue } $.getJSON(url).done (data)->$option(item).appendTo $select for item in data $ -> fillSelect "#role", "/roles", 2916367 

HTML之前

 <select id="role" name="role"></select> 

HTML之后

 <select id="role" name="role"> <option value="0">None</option> <option value="2097155">Guest</option> <option value="2916367" selected="selected">Reader</option> <option value="4186095">Manager</option> </select> 

您可以通过调用JsonConverter.SerializeObject来创buildJsonSerializerSettings,如下所示:

 var result = JsonConvert.SerializeObject ( dataObject, new JsonSerializerSettings { Converters = new [] {new StringEnumConverter()} } ); 

如果您不想使用JsonConverter属性,也可以将转换器添加到JsonConverter

 string SerializedResponse = JsonConvert.SerializeObject( objToSerialize, new Newtonsoft.Json.Converters.StringEnumConverter() ); 

它将为在序列化过程中看到的每一个enum而工作。

这是一个古老的问题,但我认为我的贡献,以防万一。 在我的项目中,我使用单独的模型来处理任何Json请求。 模型通常与具有“Json”前缀的域对象具有相同的名称。 模型使用AutoMapper进行映射。 通过使json模型声明一个string属性是一个域类的枚举,AutoMapper将parsing为string表示。

如果你想知道,我需要单独的模型Json序列化的类,因为内置的序列化器提出循环引用,否则。

希望这有助于某人。

对于.Net核心Web Api: –

 public void ConfigureServices(IServiceCollection services) { ... services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter())); ... } 

实际上,您可以使用JavaScriptConverter通过内置的JavaScriptSerializer完成此操作。 通过将您的枚举转换为Uri,您可以将其编码为一个string。

我已经描述了如何为date做这个,但也可以用于枚举。

http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/

注意到有一个Description属性时没有序列化的答案。

这是我的实现,支持Description属性。

 public class CustomStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Type type = value.GetType() as Type; if (!type.IsEnum) throw new InvalidOperationException("Only type Enum is supported"); foreach (var field in type.GetFields()) { if (field.Name == value.ToString()) { var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; writer.WriteValue(attribute != null ? attribute.Description : field.Name); return; } } throw new ArgumentException("Enum not found"); } } 

枚举:

 public enum FooEnum { // Will be serialized as "Not Applicable" [Description("Not Applicable")] NotApplicable, // Will be serialized as "Applicable" Applicable } 

用法:

 [JsonConverter(typeof(CustomStringEnumConverter))] public FooEnum test { get; set; } 

以防有人发现上述不足,我最终解决了这个过载问题:

 JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter()) 

Omer Bokhari和uri的答案的结合也是我的解决scheme,因为我想提供的价值通常不同于我在我的枚举中特有的值,如果需要,我希望能够更改我的枚举。

所以如果有人感兴趣,就是这样的:

 public enum Gender { [EnumMember(Value = "male")] Male, [EnumMember(Value = "female")] Female } class Person { int Age { get; set; } [JsonConverter(typeof(StringEnumConverter))] Gender Gender { get; set; } } 

我已经使用Newtonsoft.Json库将这个解决scheme的所有部分放在一起。 它修复了枚举问题,并使error handling更好,它在IIS托pipe服务中工作。 这是相当多的代码,所以你可以在这里find它在GitHub上: https : //github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

你必须添加一些条目到你的Web.config才能使它工作,你可以在这里看到一个示例文件: https : //github.com/jongrant/wcfjsonserializer/blob/master/Web.config

 new JavaScriptSerializer().Serialize( (from p in (new List<Person>() { new Person() { Age = 35, Gender = Gender.Male } }) select new { Age =p.Age, Gender=p.Gender.ToString() } ).ToArray()[0] );