JavaScriptSerializer - JSON-сериализация перечисления в виде строки

1162

У меня есть класс, который содержит enumсвойство, и после сериализации объекта JavaScriptSerializer, мой результат json содержит целочисленное значение перечисления, а не его string«имя». Есть ли способ получить enum как stringв моем json без необходимости создания кастома JavaScriptConverter? Возможно, есть атрибут, которым я мог бы украсить enumопределение или свойство объекта?

Например:

enum Gender { Male, Female }

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

Желаемый результат JSON:

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

В идеале ищите ответ со встроенными классами .NET Framework, если не возможны альтернативы (например, Json.net).

Омер Бохари
источник
8
Изменить на что? Ответ, получивший наибольшее количество голосов, на самом деле не отвечает на вопрос - да, он полезен в других контекстах, отсюда и при голосовании, но он практически бесполезен, если вы застряли с MS JavaScriptSerializer, как, по сути, и вы, если используете методы страницы и главное, как того требует вопрос. Принятый ответ говорит, что это невозможно. Мой ответ, пока что-то вроде взлома, выполняет свою работу.
Стивен Кеннеди

Ответы:

376

Нет, нет специального атрибута, который вы можете использовать. JavaScriptSerializerсериализует enumsих числовые значения, а не их строковое представление. Вам потребуется использовать пользовательскую сериализацию для сериализации в enumкачестве ее имени вместо числового значения.


Если вы можете использовать JSON.Net вместо того, JavaScriptSerializerчтобы увидеть ответ на этот вопрос, предоставленный OmerBakhari : JSON.net охватывает этот вариант использования (через атрибут [JsonConverter(typeof(StringEnumConverter))]) и многие другие, которые не обрабатываются встроенными сериализаторами .net. Вот ссылка, сравнивающая особенности и функциональность сериализаторов .

Мэтт Дирринг
источник
7
@Fabzter - ваше решение работало со мной, используя Json от Newtonsoft
BeemerGuy
1
@BornToCode Json.NET - это сериализатор, который ASP.NET использует по умолчанию.
BrainSlugs83
12
@ BrainSlugs83 - Вопрос был об использовании JavaScriptSerializer, а не Json.NET (и если вы посмотрите на историю изменений, вы увидите, что было внесено изменение, чтобы прояснить это), если вы используете JavaScriptSerializer, атрибут JsonConverterне будет работать.
BornToCode
50
Пожалуйста, удалите это как принятый ответ, поскольку это не решает проблему, ответ ниже с 1000+ upvotes делает.
MHGameWork
ты можешь раздражать меня
Юнцян Чен
2101

Я обнаружил, что Json.NET предоставляет именно ту функцию, которую я ищу, с StringEnumConverterатрибутом:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

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

Более подробную информацию можно найти в StringEnumConverterдокументации .

Есть другие места, чтобы настроить этот конвертер более глобально:

  • сам enum, если вы хотите, чтобы enum всегда был сериализован / десериализован как строка:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • Если кто-то хочет избежать украшения атрибутов, вы можете добавить конвертер в свой JsonSerializer (предложенный Бьорном Эгилом ):

    serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); 

    и он будет работать для каждого перечисления, которое он видит во время этой сериализации (предложено Трэвисом ).

  • или JsonConverter (предложенный бананом ):

    JsonConvert.SerializeObject(MyObject, 
        new Newtonsoft.Json.Converters.StringEnumConverter());

Кроме того, вы можете контролировать регистр и принимать ли числа, используя конструктор StringEnumConverter (NamingStrategy, Boolean) .

Омер Бохари
источник
9
Перейдите по ссылке для описания того, как использовать его в приложении asp.net mvc james.newtonking.com/archive/2008/10/16/…
RredCat
2
Вот ссылка на эту функцию: james.newtonking.com/projects/json/help/html/...
CAD парень
61
HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (new Newtonsoft.Json.Converters.StringEnumConverter ());
Игги
1
Полезно отметить, что по умолчанию ASP.NET MVC не использует Json.Net в качестве сериализатора json, и необходимо расширять Controllerили вручную переопределять каждую сериализацию.
Odys
2
Вы можете настроить конвертер (скажем, для camelCaseвывода):new StringEnumConverter { CamelCaseText = true }
Seafish
172

Добавьте ниже в ваш global.asax для JSON сериализации c # enum в виде строки

  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
источник
4
По какой-то причине я не получаю это на работу. Fiddler показывает упрямый 2, а не «Предупреждение», даже с этим на месте. Кроме того - любая причина , чтобы изменить Formattingк Indented?
sq33G
5
Третья строка из этого примера была добавлена ​​в файл App_start / webapiconfig.cs и сделала для меня хитрость в проекте ASP.NET Web API 2.1, чтобы вернуть строки для значений enum в вызовах REST (json fomat).
Грег З.
1
Есть ли способ установить это свойство только для объема запроса?
Анестис Кивраноглу
@AnestisKivranoglou просто используйте собственный сериализатор json для каждого запроса с его собственными настройками.
BrainSlugs83
3
первая настройка сериализатора с отступом не связана с вопросом операции.
user3791372
153

Ответ @Iggy устанавливает JSON-сериализацию c # enum в виде строки только для ASP.NET (веб-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

Кроме того, чтобы ваш член enum мог сериализовать / десериализовать определенный текст, используйте

System.Runtime.Serialization.EnumMember

атрибут, как это:

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

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}
Juri
источник
6
Спасибо! Я просто искал [EnumMember].
Poulad
CamelCaseTextСвойство теперь помечается как устаревшее. Новый способ создания экземпляра конвертера:new StringEnumConverter(new CamelCaseNamingStrategy())
Fiat
Большое спасибо, сделал мой день! :)
Eldoïr
39

Я не смог изменить исходную модель, как в верхнем ответе (@ob.), И я не хотел регистрировать ее глобально, как @Iggy. Поэтому я объединил https://stackoverflow.com/a/2870420/237091 и @ Iggy's https://stackoverflow.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()
        }
    })
Скотт Стаффорд
источник
это также хорошо, если у вас есть свойство, подобное этому списку <someEnumType>
Богдан
34

Комбинация ответов Omer Bokhari и uri всегда является моим решением, так как ценности, которые я хочу предоставить, обычно отличаются от того, что у меня есть в моем enum, особенно в том, что я хотел бы иметь возможность изменять свои перечисления, если мне это нужно.

Так что, если кому-то интересно, это что-то вроде этого:

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

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
Ашкан Сироус
источник
1
Я использовал JsonPropertyAttributeдля членов enum, и это работает для простых задач десериализации. К сожалению, при ручной настройке с JTokens он игнорируется. Happilly EnumMemberAttributeработает как шарм. Спасибо!
Пролог
Это работает с JavaScriptSerializer?
Стивен Кеннеди
31

Это легко сделать, добавив ScriptIgnoreатрибут в Genderсобственности, в результате чего он не сериализации, и добавив GenderStringсвойство , которое делает получить сериализации:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}
Стивен Кеннеди
источник
29
Позвольте мне попытаться объяснить. Это решение не является правильным в соответствии с дизайном патерс. Вы изменили модель в соответствии с целью просмотра. Но модель должна содержать только данные и не заботится о презентациях. Вы должны переместить эту функциональность на другой слой.
RredCat
4
На самом деле, модель используется для передачи данных от контроллера, и это контроллер, который не заботится о представлении. Введение автоматического свойства (здесь GenderString) не нарушает контроллер, который все еще использует свойство Gender, но обеспечивает легкий доступ для представления. Логическое решение.
Дима
17
@RredCat Нет ничего плохого в том, чтобы иметь определенные для вида свойства в «модели представления». ИМХО, ошибкой было бы не отделить модель представления от модели предметной области: blogs.msdn.com/b/simonince/archive/2010/01/26/…
Мариано Дезанце
5
@RredCat, даже если это было неверно по какой-то схеме, ОП ничего не говорит об этом, так что это действительно правильный ответ. (Даже если я философски могу согласиться с вашей точкой зрения.)
MEMark
10
Педантически абсурдный байк в этой ветке комментариев увлекателен.
Майк Муни
26

Эта версия ответа Стивена не меняет имя в JSON:

[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; 
        }
    }
}
mheyman
источник
3
Я считаю, что это действительно для DataContractJsonSerializerнеJavaScriptSerializer
KCD
Просто и решает проблему для меня, используя родные .NET Framework сериализаторы.
Сенатор
лучшее решение для меня, так как мне не разрешено использовать сторонние библиотеки (вопросы соответствия ISO)
Daniel Gruszczyk
Это не относится к типу сериализатора в вопросе, конечно. JavaScriptSerializer сериализует все, что не игнорируется, тогда как DataContractJsonSerializer требует атрибуты DataMember. Спасибо за крик, но, пожалуйста, обратите внимание, что вы написали мое имя неправильно :)
Стивен Кеннеди
25

Вот ответ для newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
Гуча
источник
1
Спасибо за этот ответ, мне очень помогли! Если вы хотите определить свои перечисления в PascalCase, но хотите, чтобы они были сериализованы в camelCase, вам нужно добавить trueк вашему типу JsonConverter, например, следующее:[JsonConverter(typeof(StringEnumConverter), true)]
Peet
25

Основной способ 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

st1
источник
отлично работает
DevJoe
16

Вы также можете добавить конвертер, JsonSerializerесли вы не хотите использовать JsonConverterатрибут:

string SerializedResponse = JsonConvert.SerializeObject(
     objToSerialize, 
     new Newtonsoft.Json.Converters.StringEnumConverter()
); 

Это будет работать для каждого, что enumон видит во время этой сериализации.

JerryGoyal
источник
15

Вот простое решение, которое сериализует перечисление C # на стороне сервера в JSON и использует результат для заполнения <select>элемента на стороне клиента . Это работает как для простых перечислений, так и для битовых флагов.

Я включил комплексное решение, потому что я думаю, что большинство людей, желающих сериализовать перечисление C # в JSON, также, вероятно, будут использовать его для заполнения <select>раскрывающегося списка.

Поехали:

Пример Enum

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. Он использует 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>
biofractal
источник
13

Для ядра ASP.Net Просто добавьте следующее в свой класс запуска:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });
Яхья Хуссейн
источник
1
Это работает для всех версий, а не только для ядра.
bikeman868
11

Вы можете создать JsonSerializerSettings с помощью вызова JsonConverter.SerializeObject, как показано ниже:

var result = JsonConvert.SerializeObject
            (
                dataObject,
                new JsonSerializerSettings
                {
                    Converters = new [] {new StringEnumConverter()}
                }
            );
Ян Чжан
источник
10

Заметил, что при сериализации нет ответа для сериализации.

Вот моя реализация, которая поддерживает атрибут 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");
    }
}

Enum:

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; }
Грег Р Тейлор
источник
10

Для .Net Core: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
    ...
}
PeteGO
источник
2
Если это тот из Microsoft.AspNetCore.Mvc.Formatters.Jsonпакета NuGet, кажется, это только метод расширения IMvcCoreBuilder, а не IMvcBuilder. Так что используется как services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));.
infl3x
9

В .net core 3 это теперь возможно с помощью встроенных классов в System.Text.Json:

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 }
Бьерн
источник
9

Asp.Net Core 3 с System.Text.Json

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddControllers()
        .AddJsonOptions(options => 
           options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
        );

    //...
 }
Serj-Tm
источник
8

На всякий случай, если кто-то сочтет это недостаточным, я согласился с этой перегрузкой:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
hngr18
источник
Это хорошее решение для моего текущего варианта использования: я не хочу изменять значения по умолчанию для сериализаторов, и у меня возникают проблемы с использованием атрибутов, потому что мои свойства имеют тип IList <EnumType>.
Дирк Брокгауз
5

Это старый вопрос, но я решил внести свой вклад на всякий случай. В своих проектах я использую отдельные модели для любых запросов Json. Модель обычно имеет то же имя, что и объект домена с префиксом «Json». Модели отображаются с использованием AutoMapper . Если модель json объявит строковое свойство, являющееся перечислением класса домена, AutoMapper разрешит его представление строки.

Если вам интересно, мне нужны отдельные модели для сериализованных классов Json, потому что в противном случае встроенный сериализатор предлагает циклические ссылки.

Надеюсь, это кому-нибудь поможет.

Алесь Поточник Хахонина
источник
Приятно узнать, что особенность Automapper ;-) [ScriptIgnore] атрибут удалит круговые ссылки
ledragon
1
Ой. Не знал об атрибуте. Спасибо! Вы бы использовали это на вашем Pocos? Я прибегнул к использованию определений MetadataType для любых атрибутов Poco, чтобы сохранить их в чистоте. Будет ли атрибут работать через метаданные?
Алесь Поточник Хахонина
3

На самом деле вы можете использовать JavaScriptConverter для достижения этой цели с помощью встроенного JavaScriptSerializer. Преобразуя ваше перечисление в Uri, вы можете закодировать его как строку.

Я описал, как сделать это для дат, но это может быть использовано и для перечислений. Пользовательский формат DateTime JSON для .NET JavaScriptSerializer .

Себастьян Маркбаге
источник
Очень интересное решение! Спасибо, что поделился.
Оливер
1

Не уверен, что это все еще актуально, но я должен был написать прямо в файл json, и я придумал следующее объединение нескольких ответов stackoverflow

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. Форматирует его с чистым отступом и игнорирует нули в выходных данных. Также, добавив StringEnumConverter, он печатает перечисления с их строковым значением.

Лично я считаю, что это самое чистое, что я мог придумать, не пачкая модель аннотациями.

Применение:

    internal void SaveJson(string fileName)
    {
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(@fileName))
        {
            LowercaseJsonSerializer.Serialize(file, jsonobject);
        }
    }
Kenny
источник
0

Я собрал все части этого решения, используя Newtonsoft.Jsonбиблиотеку. Он устраняет проблему с перечислением, а также значительно улучшает обработку ошибок и работает в службах, размещенных на IIS. Это довольно много кода, поэтому вы можете найти его на GitHub здесь: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Вы должны добавить несколько записей к вашему, Web.configчтобы заставить его работать, вы можете увидеть файл примера здесь: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config

Джон Грант
источник
0

А для 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)
Бенджамин Сведлов
источник
0

Чуть более перспективный вариант

Столкнувшись с тем же вопросом, мы определили, что нам нужна специальная версия, StringEnumConverterчтобы убедиться, что наши значения enum могут со временем увеличиваться без катастрофического разрушения на стороне десериализации (см. Фон ниже). С использованиемSafeEnumConverter ниже позволяет десериализации завершиться, даже если полезная нагрузка содержит значение для перечисления, у которого нет именованного определения, ближе к тому, как будет работать преобразование int-в-перечисление.

Применение:

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

или

[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, мы столкнулись с проблемой, что нам также требовалась пассивность в тех случаях, когда добавлялось новое значение перечисления, но не каждый клиент сразу знал о новом значении. В этих случаях StringEnumConverterпакет с JSON Newtonsoft выдает JsonSerializationExceptionаналогичное «Ошибка преобразования значения SomeString в тип EnumType», и тогда весь процесс десериализации завершается неудачно. Это стало для нас преградой, потому что даже если клиент планировал игнорировать / отбрасывать значение свойства, которое он не понимал, он все равно должен был быть способен десериализовать остальную часть полезной нагрузки!

пыльный
источник
-2
        Person p = new Person();
        p.Age = 35;
        p.Gender = Gender.Male;
        //1.  male="Male";
        string male = Gender.Male.ToString();

        p.Gender = Gender.Female;

        //2.  female="Female";
        string female = Enum.GetName(typeof(Gender), p.Gender);

        JObject jobj = new JObject();
        jobj["Age"] = p.Age;
        jobj["Gender"] = male;
        jobj["Gender2"] = female;

        //you result:  josn= {"Age": 35,"Gender": "Male","Gender2": "Female"}
        string json = jobj.ToString();
Zilong
источник
-5
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]  
);
Slava
источник