.NET - JSON serialization of enum as string
我有一个包含
举个例子:
1 2 3 4 5 6 7 | enum Gender { Male, Female } class Person { int Age { get; set; } Gender Gender { get; set; } } |
期望的JSON结果:
1 | {"Age": 35,"Gender":"Male" } |
我发现json.net提供了我正在寻找的具有
1 2 3 4 5 | using Newtonsoft.Json; using Newtonsoft.Json.Converters; [JsonConverter(typeof(StringEnumConverter))] public Gender Gender { get; set; } |
更多详细信息,请参阅
不,没有可以使用的特殊属性。
编辑:正如@omerbakhari json.net所指出的那样,它涵盖了这个用例(通过属性
Add the below to your global.asax for JSON serialization of c# enum as string
1 2 3 4 5 6 | 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 answer将C枚举的JSON序列化设置为仅用于ASP.NET(Web API等)的字符串。
但是为了使它也能与特殊的序列化一起工作,请将以下内容添加到您的start类中(如global.asax application_start)
1 2 3 4 5 6 7 |
有关json.net页面的详细信息
此外,要使枚举成员对特定文本进行序列化/反序列化,请使用
System.Runtime.Serialization.EnumMember
属性,如下所示:
1 2 3 4 5 6 7 8 | public enum time_zone_enum { [EnumMember(Value ="Europe/London")] EuropeLondon, [EnumMember(Value ="US/Alaska")] USAlaska } |
我无法像在顶级答案中那样更改源模型(在@ob中),而且我不想像@igy那样在全球范围内注册它。因此,我结合了https://stackoverflow.com/a/2870420/237091和@iggy的https://stackoverflow.com/a/18152942/237091,以允许在序列化对象命令本身期间设置字符串枚举转换器:
1 2 3 4 5 6 7 8 9 |
这很容易通过向
1 2 3 4 5 6 7 8 9 | class Person { int Age { get; set; } [ScriptIgnore] Gender Gender { get; set; } string GenderString { get { return Gender.ToString(); } } } |
此版本的斯蒂芬回答不会更改JSON中的名称:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | [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; } } } |
OmerBokhari和Uri的答案的组合也是我的解决方案,因为我想要提供的值通常不同于我的枚举中的值,特别是如果需要的话,我希望能够更改我的枚举。
所以如果有人感兴趣的话,应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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的答案。
1 2 3 4 5 6 7 8 9 | enum Gender { Male, Female } class Person { int Age { get; set; } [JsonConverter(typeof(StringEnumConverter))] Gender Gender { get; set; } } |
ASP.NET核心方式:
1 2 3 4 5 6 7 8 9 10 | public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); }); } } |
https://gist.github.com/regisdiogo/27F62EF83A804668EB0D9D0F63989E3E
这里有一个简单的解决方案,它将服务器端的C枚举序列化为JSON,并使用结果填充客户端的
我已经包含了端到端的解决方案,因为我认为大多数想要将C枚举序列化为JSON的人可能也会使用它来填充
下面是:
实例枚举
1 2 3 4 5 6 7 | public enum Role { None = Permission.None, Guest = Permission.Browse, Reader = Permission.Browse| Permission.Help , Manager = Permission.Browse | Permission.Help | Permission.Customise } |
使用按位ORS生成权限系统的复杂枚举。因此,不能依赖简单索引[0,1,2..]来获取枚举的整数值。
服务器端-C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
上面的代码使用nancyfx框架来处理get请求。它使用了Nancy的
生成的JSON
1 2 3 4 5 6 | [ {"Id":0,"Name":"None <hr><P>如果不想使用<wyn>JsonConverter</wyn>属性,还可以向<wyn>JsonSerializer</wyn>添加转换器:</P>[cc lang="csharp"]string SerializedResponse = JsonConvert.SerializeObject( objToSerialize, new Newtonsoft.Json.Converters.StringEnumConverter() ); |
它将适用于它在序列化过程中看到的每个
可以通过调用jsonConverter.SerializeObject创建jsonSerializerSettings,如下所示:
1 2 3 4 5 6 7 8 |
对于.NET核心Web API:
1 2 3 4 5 6 | public void ConfigureServices(IServiceCollection services) { ... services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter())); ... } |
对于ASP.NET核心,只需在启动类中添加以下内容:
1 2 3 4 5 6 |
注意,当存在description属性时,没有对序列化的应答。
这是我的实现,它支持描述属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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"); } } |
枚举:
1 2 3 4 5 6 7 8 9 | public enum FooEnum { // Will be serialized as"Not Applicable" [Description("Not Applicable")] NotApplicable, // Will be serialized as"Applicable" Applicable } |
用途:
1 2 |
这是一个古老的问题,但我认为我会做出贡献以防万一。在我的项目中,我对任何JSON请求使用单独的模型。模型通常与带有"json"前缀的域对象同名。使用automapper映射模型。通过让JSON模型声明一个字符串属性,该属性是域类上的枚举,automapper将解析为它的字符串表示。
如果您想知道,我需要为JSON序列化类使用单独的模型,因为内置序列化程序会遇到循环引用。
希望这能帮助别人。
为了防止有人发现上述不足,我最终解决了这个负担:
1 | JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter()) |
实际上,可以使用javascriptconverter通过内置的javascriptserializer来实现这一点。通过将枚举转换为URI,可以将其编码为字符串。
我已经描述了如何对日期执行此操作,但它也可以用于枚举。
http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/
不确定这是否仍然相关,但我必须直接写到一个JSON文件中,然后我将下面几个stackoverflow答案拼凑在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class LowercaseJsonSerializer { private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { ContractResolver = new LowercaseContractResolver() }; public static void Serialize(TextWriter file, object o) { JsonSerializer serializer = new JsonSerializer() { ContractResolver = new LowercaseContractResolver(), Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }; serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); serializer.Serialize(file, o); } public class LowercaseContractResolver : DefaultContractResolver { protected override string ResolvePropertyName(string propertyName) { return Char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1); } } } |
它确保我所有的JSON键都是小写的,从JSON"规则"开始。将其格式设置为完全缩进,并忽略输出中的空值。aslo通过添加一个StringEnumConverter,它可以打印带有字符串值的枚举。
就我个人而言,我觉得这是我能想到的最干净的方法,不必用注释弄脏模型。
用途:
1 2 3 4 5 6 7 8 | internal void SaveJson(string fileName) { // serialize JSON directly to a file using (StreamWriter file = File.CreateText(@fileName)) { LowercaseJsonSerializer.Serialize(file, jsonobject); } } |
我已经使用
您必须在
1 2 3 4 5 6 7 8 9 10 11 12 |