JavaScriptSerializer - 枚举作为字符串的 JSON 序列化
我有一个包含 enum
属性的类,并且在使用 JavaScriptSerializer
序列化对象时,我的 json 结果包含枚举的整数值,而不是其 string< /代码>“名称”。有没有办法在我的 json 中以
string
形式获取枚举,而无需创建自定义 JavaScriptConverter
?也许有一个属性可以用来装饰 enum
定义或对象属性?
举个例子:
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
Gender Gender { get; set; }
}
所需的 JSON 结果:
{ "Age": 35, "Gender": "Male" }
理想情况下寻找内置 .NET 框架类的答案,如果不可能,欢迎使用替代方案(如 Json.net)。
I have a class that contains an enum
property, and upon serializing the object using JavaScriptSerializer
, my json result contains the integer value of the enumeration rather than its string
"name". Is there a way to get the enum as a string
in my json without having to create a custom JavaScriptConverter
? Perhaps there's an attribute that I could decorate the enum
definition, or object property, with?
As an example:
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
Gender Gender { get; set; }
}
Desired JSON result:
{ "Age": 35, "Gender": "Male" }
Ideally looking for answer with built-in .NET framework classes, if not possible alternatives (like Json.net) are welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
不确定这是否仍然相关,但我必须直接写入 json 文件,我想出了以下将几个 stackoverflow 答案拼凑在一起的结果,
它确保我的所有 json 键都是小写的,根据 json“规则”开始。将其格式化为干净的缩进并忽略输出中的空值。同样,通过添加 StringEnumConverter,它可以打印枚举及其字符串值。
就我个人而言,我发现这是我能想到的最干净的方法,而不必用注释弄脏模型。
用法:
Not sure if this is still relevant but I had to write straight to a json file and I came up with the following piecing several stackoverflow answers together
It assures all my json keys are lowercase starting according to json "rules". Formats it cleanly indented and ignores nulls in the output. Aslo by adding a StringEnumConverter it prints enums with their string value.
Personally I find this the cleanest I could come up with, without having to dirty the model with annotations.
usage:
对于 VB.net,我发现了以下作品:
And for VB.net I found the following works:
我使用 Newtonsoft.Json 库将该解决方案的所有部分组合在一起。它修复了枚举问题,并且还使错误处理变得更好,并且它适用于 IIS 托管服务。代码相当多,因此您可以在 GitHub 上找到它:https:// /github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs
您必须向
Web.config
添加一些条目才能使其正常工作,您可以查看示例文件这里:https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config
I have put together all of the pieces of this solution using the
Newtonsoft.Json
library. It fixes the enum issue and also makes the error handling much better, and it works in IIS hosted services. It's quite a lot of code, so you can find it on GitHub here: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.csYou have to add some entries to your
Web.config
to get it to work, you can see an example file here:https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config
对于任何在 22 年 5 月需要 .NET 6 解决方案并且仍在使用 Newtonsoft 的人,您可以像这样全局注册转换器:
For anyone needing a solution in May of '22 for .NET 6 and still using Newtonsoft, you can register the converter globally like this:
我发现 Json.NET 提供了我正在寻找的确切功能一个
JsonConverter
属性,传入内置StringEnumConverter
类型:更多详细信息,请访问
StringEnumConverter
文档。还有其他地方可以更全局地配置此转换器:
枚举本身,如果您希望枚举始终被序列化/反序列化为字符串:
如果有人想要避免属性修饰,您可以将转换器添加到 JsonSerializer(由 比约恩·埃吉尔):
它将适用于序列化过程中看到的每个枚举(由 Travis 建议)。
或 JsonConverter(由 banana 建议):
此外,您可以使用 StringEnumConverter(NamingStrategy, Boolean) 构造函数。
I have found that Json.NET provides the exact functionality I'm looking for with a
JsonConverter
attribute, passing in the built-inStringEnumConverter
type:More details at available on
StringEnumConverter
documentation.There are other places to configure this converter more globally:
enum itself if you want enum always be serialized/deserialized as string:
In case anyone wants to avoid attribute decoration, you can add the converter to your JsonSerializer (suggested by Bjørn Egil):
and it will work for every enum it sees during that serialization (suggested by Travis).
or JsonConverter (suggested by banana):
Additionally you can control casing and whether numbers are still accepted by using StringEnumConverter(NamingStrategy, Boolean) constructor.
不,没有您可以使用的特殊属性。 JavaScriptSerializer 将枚举序列化为其数值而不是字符串表示形式。您需要使用自定义序列化将
enum
序列化为其名称而不是数值。如果您可以使用 JSON.Net 而不是
JavaScriptSerializer
,请参阅 对此问题的回答 < a href="https://stackoverflow.com/users/56829/omer-bokhari">Omer Bokhari:JSON.net 涵盖了此用例(通过属性[JsonConverter(typeof(StringEnumConverter))) ]
)以及许多其他未由内置 .net 序列化程序处理的内容。 这里是比较序列化器特性和功能的链接。No there is no special attribute you can use.
JavaScriptSerializer
serializesenums
to their numeric values and not their string representation. You would need to use custom serialization to serialize theenum
as its name instead of numeric value.If you can use JSON.Net instead of
JavaScriptSerializer
than see answer on this question provided by Omer Bokhari: JSON.net covers this use case (via the attribute[JsonConverter(typeof(StringEnumConverter))]
) and many others not handled by the built in .net serializers. Here is a link comparing features and functionalities of the serializers.@Iggy 答案将 c# 枚举的 JSON 序列化设置为仅适用于 ASP.NET(Web API 等)的字符串。
但要使其也适用于临时序列化,请将以下内容添加到您的启动类(例如 Global.asax Application_Start)
更多信息 在 Json.NET 页面
此外,要让您的枚举成员序列化到特定文本/反序列化到特定文本,请使用
属性,如下所示:
@Iggy answer sets JSON serialization of c# enum as string only for ASP.NET (Web API and so).
But to make it work also with ad hoc serialization, add following to your start class (like Global.asax Application_Start)
More information on the Json.NET page
Additionally, to have your enum member to serialize/deserialize to/from specific text, use the
attribute, like this:
将以下内容添加到您的 global.asax 中,以将 C# 枚举的 JSON 序列化为字符串
Add the below to your global.asax for JSON serialization of c# enum as string
在 .net core 3 中,现在可以通过 System.Text.Json 中的内置类实现这一点(编辑:System.Text.Json 也可以作为 .net core 的 NuGet 包提供2.0 和 .net Framework 4.7.2 及更高版本,根据 docs):
使用特定属性的属性装饰来配置
JsonStringEnumConverter
:如果您希望始终将枚举转换为字符串,请将属性放在枚举本身。
In .net core 3 this is now possible with the built-in classes in System.Text.Json (edit: System.Text.Json is also available as a NuGet package for .net core 2.0 and .net framework 4.7.2 and later versions according to the docs):
To configure
JsonStringEnumConverter
with attribute decoration for the specific property:If you want to always convert the enum as string, put the attribute at the enum itself.
我无法像(@ob.)的最佳答案中那样更改源模型,并且我不想像@Iggy 那样在全球范围内注册它。所以我结合了 https://stackoverflow.com/a/2870420/237091 和 @Iggy 的 https://stackoverflow.com/a/18152942/237091 允许在 SerializeObject 命令本身期间设置字符串枚举转换器:
I wasn't able to change the source model like in the top answer (of @ob.), and I didn't want to register it globally like @Iggy. So I combined https://stackoverflow.com/a/2870420/237091 and @Iggy's https://stackoverflow.com/a/18152942/237091 to allow setting up the string enum converter on during the SerializeObject command itself:
Omer Bokhari 和 uri 的答案的组合始终是我的解决方案,因为我想要提供的值通常与我的枚举中的值不同,特别是如果需要,我希望能够更改我的枚举。
所以如果有人感兴趣的话,它是这样的:
The combination of Omer Bokhari and uri 's answers is alsways my solution since the values that I want to provide is usually different from what I have in my enum specially that I would like to be able to change my enums if I need to.
So if anyone is interested, it is something like this:
通过添加
ScriptIgnore
属性添加到Gender
属性,导致其无法序列化,并添加一个GenderString
属性,确实被序列化:This is easily done by adding a
ScriptIgnore
attribute to theGender
property, causing it to not be serialised, and adding aGenderString
property which does get serialised:ASP.NET Core方式:
https://gist.github.com/regisdiogo/27f62ef83a804668eb0d9d0f63989e3e
ASP.NET Core way:
https://gist.github.com/regisdiogo/27f62ef83a804668eb0d9d0f63989e3e
此版本的 Stephen 的答案不会更改 JSON 中的名称:
This version of Stephen's answer doesn't change the name in the JSON:
这是 newtonsoft.json 的答案
Here is the answer for newtonsoft.json
Asp.Net Core 3 与 System.Text.Json
Asp.Net Core 3 with System.Text.Json
对于 .NET 6.0 如果你想使用内置的
JsonSerializer
(System.Text.Json)那么,它是开箱即用的,你只需要使用内置的
JsonStringEnumConverter
属性。例如:就是这样,但请确保您的
SomeEnumType
包含具有确切字符串值的值,否则它将引发异常。外壳似乎不敏感。参考:
For .NET 6.0 if you want to use the built-in
JsonSerializer
(System.Text.Json)Then, it comes out-of-the-box, you just need to use the built-in
JsonStringEnumConverter
attribute. For example:And that's it, BUT make sure your
SomeEnumType
contains values with the exact string values, otherwise it will throw an exception. Casing seems to be insensitive.Reference: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties?pivots=dotnet-6-0#enums-as-strings
如果您不想使用
JsonConverter
属性,您还可以向您的JsonSerializer
添加转换器:它将适用于它在过程中看到的每个
enum
那个序列化。You can also add a converter to your
JsonSerializer
if you don't want to useJsonConverter
attribute:It will work for every
enum
it sees during that serialization.对于 ASP.Net core 只需将以下内容添加到您的启动类中:
For ASP.Net core Just add the following to your Startup Class:
下面是一个简单的解决方案,它将服务器端 C# 枚举序列化为 JSON,并使用结果填充客户端
我已经包含了端到端解决方案,因为我认为大多数想要将 C# 枚举序列化为 JSON 的人也可能会使用它来填充
这里是:
示例枚举
一个使用按位或来生成权限系统的复杂枚举。因此,您不能依赖简单的索引 [0,1,2..] 来获取枚举的整数值。
服务器端 - C#
上面的代码使用 NancyFX 框架来处理 Get 请求。它使用 Nancy 的 Response.AsJson() 辅助方法 - 但不用担心,您可以使用任何标准 JSON 格式化程序,因为枚举已经被投影到准备序列化的简单匿名类型中。
生成的 JSON
客户端 - CoffeeScript
HTML 之前
HTML 之后
Here is a simple solution that serializes a server-side C# enum to JSON and uses the result to populate a client-side
<select>
element. This works for both simple enums and bitflag enums.I have included the end-to-end solution because I think most people wanting to serialize a C# enum to JSON will also probably be using it to fill a
<select>
drop-down.Here goes:
Example Enum
A complex enum that uses bitwise ORs to generate a permissions system. So you can't rely on the simple index [0,1,2..] for the integer value of the enum.
Server Side - C#
The code above uses the NancyFX framework to handle the Get request. It uses Nancy's
Response.AsJson()
helper method - but don't worry, you can use any standard JSON formatter as the enum has already been projected into a simple anonymous type ready for serialization.Generated JSON
Client Side - CoffeeScript
HTML Before
HTML After
请注意,当存在 Description 属性时,序列化没有答案。
这是我支持 Description 属性的实现。
枚举:
用法:
Noticed that there is no answer for serialization when there is a Description attribute.
Here is my implementation that supports the Description attribute.
Enum:
Usage:
您可以通过调用 JsonConverter.SerializeObject 创建 JsonSerializerSettings,如下所示:
You can create JsonSerializerSettings with the call to JsonConverter.SerializeObject as below:
对于.Net Core:-
For .Net Core :-
使用这个:
Use this:
以防万一有人发现上述内容不够,我最终解决了这个超载问题:
Just in case anybody finds the above insufficient, I ended up settling with this overload:
这是一个老问题,但我想我会贡献以防万一。在我的项目中,我对任何 Json 请求使用单独的模型。模型通常与带有“Json”前缀的域对象具有相同的名称。模型使用 AutoMapper 进行映射。通过让 json 模型声明一个作为域类枚举的字符串属性,AutoMapper 将解析为它的字符串表示形式。
如果您想知道,我需要 Json 序列化类的单独模型,因为内置序列化器会出现循环引用。
希望这对某人有帮助。
This is an old question but I thought I'd contribute just in case. In my projects I use separate models for any Json requests. A model would typically have same name as domain object with "Json" prefix. Models are mapped using AutoMapper. By having the json model declare a string property that is an enum on domain class, AutoMapper will resolve to it's string presentation.
In case you are wondering, I need separate models for Json serialized classes because inbuilt serializer comes up with circular references otherwise.
Hope this helps someone.
命名空间 System.Text.Json.Serialization 有 JsonStringEnumConverter ,可以像下面这样使用。
[JsonConverter(typeof(JsonStringEnumConverter))]
The namespace System.Text.Json.Serialization has JsonStringEnumConverter which can be used like below.
[JsonConverter(typeof(JsonStringEnumConverter))]
实际上,您可以使用 JavaScriptConverter 通过内置的 JavaScriptSerializer 来完成此操作。通过将枚举转换为 Uri,您可以将其编码为字符串。
我已经描述了如何对日期执行此操作,但它也可以用于枚举。
.NET JavaScriptSerializer 的自定义日期时间 JSON 格式。
You can actually use a JavaScriptConverter to accomplish this with the built-in JavaScriptSerializer. By converting your enum to a Uri you can encode it as a string.
I've described how to do this for dates but it can be used for enums as well.
Custom DateTime JSON Format for .NET JavaScriptSerializer.
稍微更面向未来的选项
面对同样的问题,我们确定需要一个自定义版本的 StringEnumConverter 来确保我们的枚举值可以随着时间的推移而扩展,而不会在反序列化方面发生灾难性的破坏(请参阅背景以下)。即使有效负载包含没有命名定义的枚举值,使用下面的 SafeEnumConverter 也可以完成反序列化,这更接近 int 到枚举转换的工作方式。
用法:
或
来源:
背景
当我们考虑使用
StringEnumConverter
时,我们遇到的问题是,在添加新枚举值时,我们还需要被动,但并非每个客户端都能立即意识到新的价值。在这些情况下,使用 Newtonsoft JSON 打包的StringEnumConverter
会抛出类似于“Error conversion value SomeString to type EnumType”的JsonSerializationException
,然后进行whole 反序列化进程失败。这对我们来说是一个大问题,因为即使客户端计划忽略/丢弃它不理解的属性值,它仍然需要能够反序列化其余的有效负载!A slightly more future-proof option
Facing the same question, we determined that we needed a custom version of
StringEnumConverter
to make sure that our enum values could expand over time without breaking catastrophically on the deserializing side (see background below). Using theSafeEnumConverter
below allows deserialization to finish even if the payload contains a value for the enum that does not have a named definition, closer to how int-to-enum conversion would work.Usage:
or
Source:
Background
When we looked at using the
StringEnumConverter
, the problem we had is that we also needed passivity for cases when a new enum value was added, but not every client was immediately aware of the new value. In these cases, theStringEnumConverter
packaged with Newtonsoft JSON throws aJsonSerializationException
similar to "Error converting value SomeString to type EnumType" and then the whole deserialization process fails. This was a deal breaker for us, because even if the client planned on ignoring/discarding the property value that it didn't understand, it still needed to be capable of deserializing the rest of the payload!