JavaScriptSerializer - serialização JSON de enum como string

1162

Eu tenho uma classe que contém uma enumpropriedade e, após serializar o objeto JavaScriptSerializer, meu resultado json contém o valor inteiro da enumeração, em vez de seu string"nome". Existe uma maneira de obter a enumeração como stringno meu json sem ter que criar um costume JavaScriptConverter? Talvez haja um atributo com o qual eu possa decorar a enumdefinição ou propriedade de objeto?

Como um exemplo:

enum Gender { Male, Female }

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

Resultado json desejado:

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

O ideal é procurar respostas com classes de estrutura .NET integradas, se não forem possíveis alternativas (como Json.net).

Omer Bokhari
fonte
8
Mudar para qual? A resposta mais alta votada na verdade não responde à pergunta - sim, é útil em outros contextos, daí os votos, mas não é de todo viável se você estiver preso ao MS JavaScriptSerializer, como essencialmente se estiver usando métodos de página e , o mais importante, conforme exigido pela pergunta. A resposta aceita diz que não é possível. Minha resposta enquanto um pouco de hack faz o trabalho.
Stephen Kennedy

Respostas:

376

Não, não há nenhum atributo especial que você possa usar. JavaScriptSerializerserializa enumspara seus valores numéricos e não para sua representação de string. Você precisaria usar a serialização personalizada para serializar o enumnome como nome, em vez do valor numérico.


Se você pode usar o JSON.Net em vez de JavaScriptSerializerver a resposta dessa pergunta fornecida pelo OmerBakhari : o JSON.net cobre esse caso de uso (por meio do atributo [JsonConverter(typeof(StringEnumConverter))]) e muitos outros não tratados pelos serializadores .net incorporados. Aqui está um link comparando recursos e funcionalidades dos serializadores .

Matt Dearing
fonte
7
@Fabzter - sua solução trabalhou comigo usando de Newtonsoft Json
BeemerGuy
1
@BornToCode Json.NET é o serializador que o ASP.NET usa por padrão.
BrainSlugs83
12
@ BrainSlugs83 - A pergunta era sobre o uso do JavaScriptSerializer, não do Json.NET (e, se você examinar o histórico de revisões, verá uma edição para esclarecer isso), se você usar o JavaScriptSerializer, o atributo JsonConverternão funcionará.
BornToCode
50
Por favor, remova-o como a resposta aceita, pois não resolve o problema, a resposta abaixo com mais de 1000 upvotes DOES.
MHGameWork
u poderia me irrita
Yongqiang Chen
2101

Eu descobri que o Json.NET fornece a funcionalidade exata que estou procurando com um StringEnumConverteratributo:

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

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

Mais detalhes estão disponíveis na StringEnumConverterdocumentação .

Existem outros locais para configurar este conversor de maneira mais global:

  • enum se você quiser que o enum sempre seja serializado / desserializado como string:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • Caso alguém queira evitar a decoração de atributos, você pode adicionar o conversor ao seu JsonSerializer (sugerido por Bjørn Egil ):

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

    e funcionará para todas as enumerações exibidas durante a serialização (sugeridas por Travis ).

  • ou JsonConverter (sugerido por banana ):

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

Além disso, você pode controlar o caso e se os números ainda são aceitos usando o construtor StringEnumConverter (NamingStrategy, Boolean) .

Omer Bokhari
fonte
9
Siga por ligação para descrição de como usá-lo em asp.net aplicativo mvc james.newtonking.com/archive/2008/10/16/...
RredCat
2
Aqui está o link para essa função: james.newtonking.com/projects/json/help/html/…
CAD bloke
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 ());
Iggy
1
É útil observar que, por padrão, o ASP.NET MVC não usa o Json.Net como serializador json e é necessário estender Controllerou substituir manualmente todas as serializações.
Odys
2
Você pode personalizar o conversor (por exemplo, para camelCasesaída):new StringEnumConverter { CamelCaseText = true }
Seafish
172

Adicione o seguinte ao global.asax para serialização JSON de c # enum como string

  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
fonte
4
Por alguma razão, não estou conseguindo fazer isso funcionar. O violinista mostra um 2 teimoso em vez de 'Aviso', mesmo com isso. Além disso - alguma razão para mudar Formattingpara Indented?
sq33G
5
A terceira linha deste exemplo foi adicionada ao arquivo App_start / webapiconfig.cs e fez um truque para mim em um projeto da ASP.NET Web API 2.1 para retornar seqüências de caracteres para valores de enumeração em chamadas REST (json fomat).
Greg Z.
1
Existe uma maneira de definir essa propriedade apenas por escopo da solicitação?
Anestis Kivranoglou 31/03
O @AnestisKivranoglou apenas usa um serializador json personalizado por solicitação com suas próprias configurações.
BrainSlugs83
3
a primeira configuração serializada de recuado não está relacionada à questão operacional.
user3791372
153

A resposta @Iggy define a serialização JSON de c # enum como string apenas para o ASP.NET (Web API e assim).

Mas, para fazê-lo funcionar também com a serialização ad hoc, adicione o seguinte à sua classe inicial (como 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;
});

Mais informações na página Json.NET

Além disso, para que seu membro enum serialize / desserialize de / para um texto específico, use o

System.Runtime.Serialization.EnumMember

atributo, assim:

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

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}
Juri
fonte
6
Obrigado! Eu estava apenas procurando [EnumMember].
Poulad 16/09/19
A CamelCaseTextpropriedade agora está marcada como obsoleta. Nova maneira de instanciar o conversor:new StringEnumConverter(new CamelCaseNamingStrategy())
fiat
Muito obrigado, fez o meu dia! :)
Eldoïr 1/11/19
39

Não consegui alterar o modelo de origem como na resposta superior (de @ob.) E não queria registrá-lo globalmente como @Iggy. Então eu combinei https://stackoverflow.com/a/2870420/237091 e @ de Iggy https://stackoverflow.com/a/18152942/237091 para permitir a configuração do conversor de corda enum durante o próprio comando 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()
        }
    })
Scott Stafford
fonte
isso também funciona bem se você tiver uma propriedade como esta List <someEnumType>
Bogdan
34

A combinação das respostas de Omer Bokhari e uri é sempre a minha solução, já que os valores que eu quero fornecer geralmente são diferentes dos que tenho na minha enumeração, especialmente que eu gostaria de poder alterar minha enumeração, se necessário.

Portanto, se alguém estiver interessado, é algo como isto:

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

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
Ashkan Sirous
fonte
1
Eu estava usando JsonPropertyAttributepara membros enum e está trabalhando para tarefas simples de desserialização. Infelizmente, durante ajustes manuais com JTokens, isso é ignorado. Happilly EnumMemberAttributefunciona como um encanto. Obrigado!
Prolog
Isso funciona com JavaScriptSerializer?
Stephen Kennedy
31

Isso é feito facilmente adicionando um ScriptIgnoreatributo à Genderpropriedade, fazendo com que ele não seja serializado e adicionando uma GenderStringpropriedade que é serializada:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}
Stephen Kennedy
fonte
29
Deixe-me tentar explicar. Esta solução não está correta de acordo com os padrões de design. Você modificou o modelo de acordo com a finalidade da exibição. Mas o modelo precisa conter apenas dados e não se importa com apresentações. Você precisa mover essa funcionalidade para a outra camada.
RredCat
4
Na verdade, o Model é usado para passar dados do controlador, e é o controlador, que não se importa com a apresentação. A introdução da propriedade automatizada (GenderString aqui) não quebra o controlador, que ainda usa a propriedade Gender, mas fornece fácil acesso para uma visualização. Solução lógica.
Dima 16/07
17
@RredCat Não há nada de errado em ter propriedades específicas de exibição no "modelo de exibição". IMHO o erro seria não para dividir o modelo de vista do modelo de domínio: blogs.msdn.com/b/simonince/archive/2010/01/26/...
Mariano Desanze
5
@RredCat, mesmo que estivesse incorreto de acordo com algum padrão, o OP não diz nada sobre isso, então essa é realmente uma resposta correta. (Mesmo se eu filosoficamente pode concordar com o seu ponto.)
MEMark
10
O desvio de bicicleta pedanticamente absurdo neste tópico de comentário é fascinante.
Mike Mooney
26

Esta versão da resposta de Stephen não altera o nome no 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
fonte
3
Eu acredito que isso é válido para o DataContractJsonSerializernãoJavaScriptSerializer
KCD
Simples e resolve o problema para mim usando serializadores do .NET framework nativos.
O senador
melhor solução para mim como eu não estou autorizado a usar bibliotecas 3o partido (questões de cumprimento dos requisitos da ISO)
Daniel Gruszczyk
Isso não é para o tipo de serializador na questão, é claro. JavaScriptSerializer serializa tudo o que não é ignorado, enquanto DataContractJsonSerializer requer atributos DataMember. Obrigado pelo grito para fora, mas por favor note que você soletrou meu nome errado :)
Stephen Kennedy
25

Aqui está a resposta para newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
GuCa
fonte
1
Obrigado por esta resposta, me ajudou muito! Se você deseja definir suas enumerações no PascalCase, mas deseja que elas sejam serializadas no camelCase, é necessário adicionar trueao seu tipo JsonConverter desta maneira:[JsonConverter(typeof(StringEnumConverter), true)]
Peet
25

Maneira principal do 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
fonte
funciona perfeitamente
DevJoe 31/01
16

Você também pode adicionar um conversor ao seu JsonSerializerse não quiser usar o JsonConverteratributo:

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

Ele funcionará para tudo o enumque vir durante a serialização.

JerryGoyal
fonte
15

Aqui está uma solução simples que serializa um C # enum do lado do servidor para JSON e usa o resultado para preencher um lado do cliente <select> elemento do . Isso funciona para enumerações simples e enumerações de bitflag.

Eu incluí a solução de ponta a ponta porque acho que a maioria das pessoas que desejam serializar um enum C # para JSON também provavelmente o usará para preencher um <select>menu suspenso.

Aqui vai:

Exemplo Enum

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

Um enum complexo que usa ORs bit a bit para gerar um sistema de permissões. Portanto, você não pode confiar no índice simples [0,1,2 ..] para o valor inteiro da enumeração.

Lado do servidor - 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);
};

O código acima usa a estrutura NancyFX para manipular a solicitação Get. Ele usa o Response.AsJson()método auxiliar de Nancy - mas não se preocupe, você pode usar qualquer formatador JSON padrão, pois a enum já foi projetada em um tipo anônimo simples, pronto para serialização.

JSON gerado

[
    {"Id":0,"Name":"None"},
    {"Id":2097155,"Name":"Guest"},
    {"Id":2916367,"Name":"Reader"},
    {"Id":4186095,"Name":"Manager"}
]

Lado do cliente - 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 Antes

<select id="role" name="role"></select>

HTML depois

<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
fonte
13

Para o núcleo do ASP.Net, adicione o seguinte à sua classe de inicialização:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });
Yahya Hussein
fonte
1
Isso funciona para todas as versões, não apenas para o núcleo.
bikeman868
11

Você pode criar JsonSerializerSettings com a chamada para JsonConverter.SerializeObject como abaixo:

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

Percebeu que não há resposta para serialização quando há um atributo Descrição.

Aqui está minha implementação que suporta o atributo Descrição.

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
}

Uso:

[JsonConverter(typeof(CustomStringEnumConverter))]
public FooEnum test { get; set; }
Greg R Taylor
fonte
10

Para .Net Core: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
    ...
}
PeteGO
fonte
2
Se este é o do Microsoft.AspNetCore.Mvc.Formatters.Jsonpacote NuGet, parece ser apenas um método de extensão IMvcCoreBuilder, não IMvcBuilder. Então é usado assim services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));.
infl3x
9

Agora, no .net core 3, agora é possível com as classes internas no 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);

Para configurar JsonStringEnumConvertercom decoração de atributo para a propriedade específica:

using System.Text.Json.Serialization;

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

Se você deseja sempre converter o enum como string, coloque o atributo no próprio enum.

[JsonConverter(typeof(JsonStringEnumConverter))] 
enum Gender { Male, Female }
Björn
fonte
9

Asp.Net Core 3 com System.Text.Json

public void ConfigureServices(IServiceCollection services)
{

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

    //...
 }
Serj-Tm
fonte
8

Apenas no caso de alguém achar o acima insuficiente, acabei resolvendo com essa sobrecarga:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
hngr18
fonte
Esta é uma boa solução para um caso de uso atual meu: não quero alterar os padrões dos serializadores e tenho problemas ao usar atributos, porque minhas propriedades são do tipo IList <EnumType>.
Dirk Brockhaus
5

Esta é uma pergunta antiga, mas pensei em contribuir apenas para o caso. Nos meus projetos, uso modelos separados para quaisquer solicitações Json. Um modelo normalmente teria o mesmo nome que o objeto de domínio com o prefixo "Json". Os modelos são mapeados usando o AutoMapper . Ao fazer com que o modelo json declare uma propriedade de string que é uma enumeração na classe de domínio, o AutoMapper resolverá sua apresentação de string.

Caso você esteja se perguntando, preciso de modelos separados para classes serializadas Json, pois o serializador embutido apresenta referências circulares.

Espero que isso ajude alguém.

Ales Potocnik Hahonina
fonte
Bom para saber que recurso de AutoMapper ;-) [ScriptIgnore] atributo irá remover referências circulares
ledragon
1
Oh. Não sabia sobre o atributo. Obrigado! Você usaria isso no seu Pocos? Eu usei as definições de MetadataType para quaisquer atributos do Poco apenas para mantê-los limpos. O atributo ainda funcionaria via metadados?
Ales Potocnik Hahonina
3

Você pode realmente usar um JavaScriptConverter para fazer isso com o JavaScriptSerializer interno. Ao converter seu enum em um Uri, você pode codificá-lo como uma string.

Descrevi como fazer isso para datas, mas também pode ser usado para enumerações. Formato JSON DateTime personalizado para .NET JavaScriptSerializer .

Sebastian Markbåge
fonte
Solução muito interessante! Obrigado por compartilhar.
Oliver
1

Não tenho certeza se isso ainda é relevante, mas tive que escrever diretamente em um arquivo json e vim com as seguintes informações reunindo várias respostas de fluxo de pilha

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

Ele garante que todas as minhas chaves json sejam minúsculas, iniciando de acordo com as "regras" do json. Formata o recuo limpo e ignora valores nulos na saída. Além disso, adicionando um StringEnumConverter, ele imprime enumerações com seu valor de string.

Pessoalmente, acho isso o mais limpo possível, sem ter que sujar o modelo com anotações.

uso:

    internal void SaveJson(string fileName)
    {
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(@fileName))
        {
            LowercaseJsonSerializer.Serialize(file, jsonobject);
        }
    }
kenny
fonte
0

Reuni todas as partes desta solução usando a Newtonsoft.Jsonbiblioteca. Ele corrige o problema da enumeração e também melhora o tratamento de erros e funciona nos serviços hospedados no IIS. É bastante código, então você pode encontrá-lo no GitHub aqui: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Você precisa adicionar algumas entradas ao seu Web.configpara que funcione. Você pode ver um arquivo de exemplo aqui: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config

Jon Grant
fonte
0

E para VB.net eu encontrei os seguintes trabalhos:

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)
Benjamin Swedlove
fonte
0

Uma opção um pouco mais à prova de futuro

Enfrentando a mesma pergunta, determinamos que precisávamos de uma versão personalizada StringEnumConverterpara garantir que nossos valores de enum pudessem se expandir ao longo do tempo sem quebrar catastroficamente no lado de desserialização (veja o plano de fundo abaixo). Usando oSafeEnumConverter abaixo permite que a desserialização termine, mesmo que a carga útil contenha um valor para a enumeração que não tenha uma definição nomeada, mais próximo de como a conversão de intentenum funcionaria.

Uso:

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

ou

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

Fonte:

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;
    }
}

fundo

Quando analisamos o uso do StringEnumConverter, o problema que tivemos é que também precisávamos de passividade para casos em que um novo valor de enum foi adicionado, mas nem todos os clientes estavam imediatamente cientes do novo valor. Nesses casos, o StringEnumConverterempacotado com o Newtonsoft JSON lança um JsonSerializationExceptionsemelhante a "Erro ao converter o valor SomeString para digitar EnumType" e, em seguida, todo o processo de desserialização falha. Isso foi um rompimento de negócios para nós, porque, mesmo que o cliente planejasse ignorar / descartar o valor da propriedade que não entendia, ainda precisava ser capaz de desserializar o restante da carga útil!

Poeirento
fonte
-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
fonte
-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
fonte