我有一个包含枚举属性的类,在使用JavaScriptSerializer序列化对象时,我的json结果包含枚举的整数值,而不是它的字符串“name”。有没有一种方法来获得枚举作为字符串在我的json而不必创建一个自定义JavaScriptConverter?也许有一个属性,我可以装饰枚举定义,或对象属性?

举个例子:

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }
    Gender Gender { get; set; }
}

期望的JSON结果:

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

理想情况下,用内置的。net框架类来寻找答案,如果没有可能的替代方案(如Json.net)也是受欢迎的。


当前回答

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

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

是:

枚举例子

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

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

服务器端- 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格式化器,因为枚举已经被投射到一个简单的匿名类型,可以序列化。

生成的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>

其他回答

在。net core 3中,现在可以使用System.Text.Json中的内置类来实现这一点(编辑:System.Text.Json也可以作为。net core 2.0和。net framework 4.7.2以及更高版本的NuGet包,根据文档):

var person = new Person();
// Create and add a converter which will use the string representation instead of the numeric value.
var stringEnumConverter = new System.Text.Json.Serialization.JsonStringEnumConverter();
JsonSerializerOptions opts = new JsonSerializerOptions();
opts.Converters.Add(stringEnumConverter);
// Generate json string.
var json = JsonSerializer.Serialize<Person>(person, opts);

为特定的属性配置JsonStringEnumConverter属性装饰:

using System.Text.Json.Serialization;

[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }

如果您希望始终将枚举转换为字符串,请将属性放在枚举本身。

[JsonConverter(typeof(JsonStringEnumConverter))] 
enum Gender { Male, Female }

您可以通过调用JsonConverter来创建JsonSerializerSettings。SerializeObject如下:

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

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

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

是:

枚举例子

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

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

服务器端- 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格式化器,因为枚举已经被投射到一个简单的匿名类型,可以序列化。

生成的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>

对于任何在22年5月就需要。net 6解决方案并且仍在使用Newtonsoft的人来说,你可以像这样全局注册转换器:

var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddControllers(options => options.RespectBrowserAcceptHeader = true)
.AddNewtonsoftJson(opt =>
{
    opt.SerializerSettings.ContractResolver = new DefaultContractResolver();
    opt.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
})
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters();

对于VB.net,我找到了以下作品:

Dim sec = New Newtonsoft.Json.Converters.StringEnumConverter()
sec.NamingStrategy() = New Serialization.CamelCaseNamingStrategy

Dim JSON_s As New JsonSerializer
JSON_s.Converters.Add(sec)

Dim jsonObject As JObject
jsonObject = JObject.FromObject(SomeObject, JSON_s)
Dim text = jsonObject.ToString

IO.File.WriteAllText(filePath, text)