我有一个包含枚举属性的类,在使用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)也是受欢迎的。


当前回答

为了防止有人发现上面的内容不够充分,我最终列出了以下内容:

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

其他回答

对于任何在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();

@Iggy回答设置JSON序列化c# enum字符串仅为ASP。NET (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的信息。网络页面

此外,要让枚举成员序列化/反序列化特定文本,请使用

System.Runtime.Serialization.EnumMember

属性,像这样:

public enum time_zone_enum
{
    [EnumMember(Value = "Europe/London")] 
    EuropeLondon,

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}

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

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

一个稍微更经得起考验的选择

面对同样的问题,我们决定需要一个自定义版本的StringEnumConverter,以确保枚举值可以随着时间的推移而扩展,而不会在反序列化方面发生灾难性的破坏(参见下面的背景)。使用下面的SafeEnumConverter允许反序列化完成,即使有效负载包含没有命名定义的枚举的值,这更接近于int-to-enum转换的工作方式。

用法:

[SafeEnumConverter]
public enum Colors
{
    Red,
    Green,
    Blue,
    Unsupported = -1
}

or

[SafeEnumConverter((int) Colors.Blue)]
public enum Colors
{
    Red,
    Green,
    Blue
}

来源:

public class SafeEnumConverter : StringEnumConverter
{
    private readonly int _defaultValue;

    public SafeEnumConverter()
    {
        // if you've been careful to *always* create enums with `0` reserved
        // as an unknown/default value (which you should), you could use 0 here. 
        _defaultValue = -1;
    }

    public SafeEnumConverter(int defaultValue)
    {
        _defaultValue = defaultValue;
    }

    /// <summary>
    /// Reads the provided JSON and attempts to convert using StringEnumConverter. If that fails set the value to the default value.
    /// </summary>
    /// <returns>The deserialized value of the enum if it exists or the default value if it does not.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch
        {
            return Enum.Parse(objectType, $"{_defaultValue}");
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return base.CanConvert(objectType) && objectType.GetTypeInfo().IsEnum;
    }
}

背景

当我们考虑使用StringEnumConverter时,我们遇到的问题是,当添加了一个新的enum值时,我们还需要被动式,但并不是每个客户端都能立即意识到新值。在这些情况下,与Newtonsoft JSON打包的StringEnumConverter抛出类似于“将SomeString值转换为EnumType类型错误”的JsonSerializationException,然后整个反序列化过程失败。这对我们来说是一个问题,因为即使客户端计划忽略/丢弃它不理解的属性值,它仍然需要能够反序列化剩余的有效负载!

ASP。NET核心方式:

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