c# - stringenumconverter




JSON序列化为字符串的枚举 (13)

@Iggy答案将c#enum的JSON序列化设置为仅适用于ASP.NET的Web应用程序(Web API等)。

但为了使其在特定序列化中也能正常工作,请在开始类中添加以下内容(如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
}

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

举个例子:

enum Gender { Male, Female }

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

期望的json结果:

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

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

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

public enum Gender
{
   [EnumMember(Value = "male")] 
   Male,
   [EnumMember(Value = "female")] 
   Female
}

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

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

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


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

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


对于.Net Core Web Api: -

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

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

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

我使用Newtonsoft.Json库将所有这些解决方案组合在一起。 它修复了枚举问题,并使错误处理更好,并且它在IIS托管服务中工作。 它有相当多的代码,所以你可以在GitHub上找到它: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cshttps://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

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


我无法像在顶部答案(@ob)中那样更改源模型,我也不想像@Iggy那样在全局范围内注册它。 所以我结合了https://.com/a/2870420/237091和@ Iggy的https://.com/a/18152942/237091以允许在SerializeObject命令本身期间设置字符串枚举转换器:

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

有一个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; }

这是一个简单的解决方案,它将服务器端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
}

一个使用按位或运算来生成权限系统的复杂枚举。 所以你不能依赖简单索引[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格式化程序,因为枚举已经投影到一个简单的匿名类型中,以便序列化。

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

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

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

希望这可以帮助某人。


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]  
);




javascriptserializer