枚举的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" }
不,没有特殊的属性可以使用。 JavaScriptSerializer
将enums
序列化为它们的数字值,而不是它们的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] );