JavaScriptSerializer - serialisasi JSON dari enum sebagai string


1162

Saya memiliki kelas yang berisi enumproperti, dan setelah serialisasi objek menggunakan JavaScriptSerializer, hasil json saya berisi nilai integer enumerasi daripada string"namanya". Apakah ada cara untuk mendapatkan enum sebagai stringdi json saya tanpa harus membuat kebiasaan JavaScriptConverter? Mungkin ada atribut yang saya dapat menghias enumdefinisi, atau properti objek, dengan?

Sebagai contoh:

enum Gender { Male, Female }

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

Hasil json yang diinginkan:

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

Idealnya mencari jawaban dengan built-in kelas .NET framework, jika tidak memungkinkan alternatif (seperti Json.net) dipersilakan.


8
Ubah yang mana? Jawaban tertinggi yang dipilih tidak benar-benar menjawab pertanyaan - ya itu berguna dalam konteks lain, karena itu suara, tetapi itu tidak dapat digunakan sama sekali jika Anda terjebak dengan MS JavaScriptSerializer, karena pada dasarnya Anda menggunakan metode halaman dan , yang paling penting, seperti yang dipersyaratkan oleh pertanyaan. Jawaban yang diterima mengatakan itu tidak mungkin. Jawaban saya sementara sedikit peretasan menyelesaikan pekerjaan.
Stephen Kennedy

Jawaban:


376

Tidak, tidak ada atribut khusus yang dapat Anda gunakan. JavaScriptSerializercerita bersambung enumske nilai numerik mereka dan bukan representasi string mereka. Anda perlu menggunakan serialisasi khusus untuk membuat serialisasi enumsebagai namanya alih-alih nilai numerik.


Jika Anda dapat menggunakan JSON.Net JavaScriptSerializerdaripada melihat jawaban pada pertanyaan ini yang disediakan oleh OmerBakhari : JSON.net membahas use case ini (melalui atribut [JsonConverter(typeof(StringEnumConverter))]) dan banyak lainnya yang tidak ditangani oleh serializers .net yang dibangun. Berikut ini tautan yang membandingkan fitur dan fungsi serialis .


7
@Fabzter - solusi Anda bekerja dengan saya menggunakan Newtonsoft's Json
BeemerGuy

1
@BornToCode Json.NET adalah serializer yang digunakan ASP.NET secara default.
BrainSlugs83

12
@ BrainSlugs83 - Pertanyaannya adalah tentang menggunakan JavaScriptSerializer, bukan Json.NET (dan jika Anda melihat riwayat revisi Anda akan melihat bahwa ada edit untuk menjelaskannya), jika Anda menggunakan JavaScriptSerializer, atribut JsonConvertertidak akan berfungsi.
BornToCode

50
Harap hapus ini sebagai jawaban yang diterima karena tidak menyelesaikan masalah, jawaban di bawah ini dengan 1000+ upvotes DOES.
MHGameWork

bisakah kamu menjawab saya
Yongqiang Chen

2101

Saya telah menemukan bahwa Json.NET menyediakan fungsionalitas tepat yang saya cari dengan StringEnumConverteratribut:

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

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

Lebih detail tersedia di StringEnumConverterdokumentasi .

Ada tempat lain untuk mengkonfigurasi konverter ini secara lebih global:

  • enum sendiri jika Anda ingin enum selalu serial / deserialized sebagai string:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • Jika ada yang ingin menghindari dekorasi atribut, Anda dapat menambahkan konverter ke JsonSerializer Anda (disarankan oleh Bjørn Egil ):

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

    dan itu akan bekerja untuk setiap enum yang dilihatnya selama serialisasi itu (disarankan oleh Travis ).

  • atau JsonConverter (disarankan oleh pisang ):

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

Selain itu Anda dapat mengontrol casing dan apakah nomor masih diterima dengan menggunakan konstruktor StringEnumConverter (NamingStrategy, Boolean) .


9
Ikuti dengan tautan untuk deskripsi bagaimana menggunakannya di asp.net mvc aplikasi james.newtonking.com/archive/2008/10/16/…
RredCat


61
HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (Newtonsoft.Json.Converters baru. StringEnumConverter ());
Iggy

1
Sangat berguna untuk mencatat secara default ASP.NET MVC tidak menggunakan Json.Net sebagai serializer json dan seseorang perlu memperpanjang Controlleratau secara manual menimpa setiap serialisasi.
Odys

2
Anda dapat menyesuaikan konverter (misalnya, untuk camelCaseoutput):new StringEnumConverter { CamelCaseText = true }
Seafish

172

Tambahkan di bawah ini ke global.asax Anda untuk serialisasi JSON dari c # enum sebagai 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());

4
Untuk beberapa alasan, saya tidak membuat ini berfungsi. Fiddler menunjukkan 2 yang keras kepala daripada 'Peringatan', bahkan dengan ini di tempat. Juga - ada alasan mengapa harus mengubah Formattingke Indented?
sq33G

5
Baris ketiga dari contoh ini ditambahkan ke file App_start / webapiconfig.cs dan melakukan trik untuk saya dalam proyek ASP.NET Web API 2.1 untuk mengembalikan string untuk nilai enum dalam panggilan REST (json fomat).
Greg Z.

1
Apakah ada cara untuk Menetapkan properti ini hanya per Lingkup Permintaan?
Anestis Kivranoglou

@AnestisKivranoglou gunakan saja serializer json khusus per permintaan dengan pengaturannya sendiri.
BrainSlugs83

3
pengaturan serializer pertama dari indentasi tidak terkait dengan pertanyaan op.
user3791372

153

@Iggy answer menetapkan serialisasi JSON dari c # enum sebagai string hanya untuk ASP.NET (API Web dan sebagainya).

Tetapi untuk membuatnya bekerja juga dengan serialisasi ad hoc, tambahkan berikut ke kelas awal Anda (seperti 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;
});

Informasi lebih lanjut tentang halaman Json.NET

Selain itu, untuk meminta anggota enum Anda membuat cerita bersambung / deserialize ke / dari teks tertentu, gunakan

System.Runtime.Serialization.EnumMember

atribut, seperti ini:

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

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

6
Terima kasih! Saya hanya mencari [EnumMember].
Poulad

The CamelCaseTextproperti sekarang ditandai usang. Cara baru untuk instantiate konverter:new StringEnumConverter(new CamelCaseNamingStrategy())
fiat

Terima kasih banyak, buat hari saya! :)
Eldoïr

39

Saya tidak dapat mengubah model sumber seperti pada jawaban teratas (dari @ob.), Dan saya tidak ingin mendaftarkannya secara global seperti @Iggy. Jadi saya menggabungkan https://stackoverflow.com/a/2870420/237091 dan @ Iggy's https://stackoverflow.com/a/18152942/237091 untuk memungkinkan pengaturan konverter string pada saat perintah SerializeObject itu sendiri:

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

ini juga bagus sekali jika Anda memiliki properti seperti Daftar ini <someEnumType>
Bogdan

34

Kombinasi jawaban Omer Bokhari dan uri adalah selalu merupakan solusi saya karena nilai yang ingin saya berikan biasanya berbeda dari apa yang saya miliki di enum saya khususnya bahwa saya ingin dapat mengubah enum saya jika saya perlu.

Jadi, jika ada yang tertarik, ini adalah sesuatu seperti ini:

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
Saya menggunakan JsonPropertyAttributeuntuk anggota enum dan bekerja untuk tugas deserializtion sederhana. Sayangnya, selama tweak manual dengan JTokens itu diabaikan. Happilly EnumMemberAttributebekerja seperti pesona. Terima kasih!
Prolog

Itu berhasil JavaScriptSerializer?
Stephen Kennedy

31

Hal ini mudah dilakukan dengan menambahkan ScriptIgnoreatribut ke Genderproperti, menyebabkan ia tidak serial, dan menambahkan GenderStringproperti yang tidak mendapatkan serial:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}

29
Biarkan saya coba jelaskan. Solusi ini tidak benar sesuai dengan pola desain. Anda memodifikasi model sesuai dengan tujuan tampilan. Tetapi model harus mengandung data saja dan tidak peduli tentang presentasi. Anda harus memindahkan fungsi ini di lapisan lain.
RredCat

4
Sebenarnya, Model digunakan untuk melewatkan data dari controller, semutnya adalah controller, yang tidak peduli dengan presentasi. Pengenalan properti otomatis (GenderString di sini) tidak merusak controller, yang masih menggunakan properti Gender, tetapi menyediakan akses mudah untuk tampilan. Solusi logis.
Dima

17
@RredCat Tidak ada yang salah dengan memiliki properti tampilan-spesifik di "model tampilan". IMHO kesalahannya adalah tidak memisahkan model tampilan dari model domain: blogs.msdn.com/b/simonince/archive/2010/01/26/…
Mariano Desanze

5
@RredCat, bahkan jika itu salah menurut beberapa pola, OP tidak mengatakan apa-apa tentang ini, jadi ini memang jawaban yang benar. (Bahkan jika secara filosofis saya setuju dengan pendapat Anda.)
MEMark

10
Sepeda shedding pedantically absurd di utas komentar ini sangat menarik.
Mike Mooney

26

Versi jawaban Stephen ini tidak mengubah nama di 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; 
        }
    }
}

3
Saya percaya ini berlaku untuk yang DataContractJsonSerializertidakJavaScriptSerializer
KCD

Sederhana dan memecahkan masalah bagi saya menggunakan serializers .NET framework asli.
Senator

solusi terbaik bagi saya karena saya tidak diizinkan menggunakan perpustakaan pihak ke-3 (masalah
kepatuhan

Ini bukan untuk jenis serialiser dalam pertanyaan, tentu saja. JavaScriptSerializer membuat serial segala sesuatu yang tidak diabaikan, sedangkan DataContractJsonSerializer membutuhkan atribut DataMember. Terima kasih atas teriakannya, tetapi harap dicatat Anda salah mengeja nama saya :)
Stephen Kennedy

25

Inilah jawaban untuk newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

1
Terima kasih atas jawaban ini, banyak membantu saya! Jika Anda ingin mendefinisikan enum Anda di PascalCase, tetapi Anda ingin agar serial di camelCase maka Anda perlu menambahkan trueke jenis JsonConverter Anda seperti ini:[JsonConverter(typeof(StringEnumConverter), true)]
Peet


16

Anda juga dapat menambahkan konverter ke Anda JsonSerializerjika Anda tidak ingin menggunakan JsonConverteratribut:

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

Ini akan bekerja untuk setiap enumyang dilihatnya selama serialisasi itu.


15

Berikut ini adalah solusi sederhana yang membuat serial C-enum sisi-server untuk JSON dan menggunakan hasilnya untuk mengisi sisi klien <select> elemen . Ini berfungsi untuk enum sederhana dan enum bitflag.

Saya telah memasukkan solusi ujung ke ujung karena saya pikir sebagian besar orang yang ingin membuat serial C # enum ke JSON mungkin juga akan menggunakannya untuk mengisi <select>drop-down.

Ini dia:

Contoh Enum

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

Enum kompleks yang menggunakan OR bitwise untuk menghasilkan sistem izin. Jadi Anda tidak bisa mengandalkan indeks sederhana [0,1,2 ..] untuk nilai integer enum.

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

Kode di atas menggunakan kerangka kerja NancyFX untuk menangani permintaan Dapatkan. Ini menggunakan Response.AsJson()metode pembantu Nancy - tetapi jangan khawatir, Anda dapat menggunakan formatter JSON standar karena enum telah diproyeksikan menjadi jenis anonim sederhana yang siap untuk serialisasi.

JSON yang dihasilkan

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

Sisi Klien - 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 Sebelumnya

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

HTML Setelah

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

13

Untuk inti ASP.Net Cukup tambahkan berikut ini ke Kelas Startup Anda:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });

1
Ini berfungsi untuk semua versi, bukan hanya inti.
bikeman868

11

Anda dapat membuat JsonSerializerSettings dengan panggilan ke JsonConverter.SerializeObject seperti di bawah ini:

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

10

Melihat bahwa tidak ada jawaban untuk serialisasi ketika ada atribut Deskripsi.

Ini implementasi saya yang mendukung atribut Deskripsi.

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
}

Pemakaian:

[JsonConverter(typeof(CustomStringEnumConverter))]
public FooEnum test { get; set; }

10

Untuk .Net Core: -

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

2
Jika ini adalah salah satu dari Microsoft.AspNetCore.Mvc.Formatters.Jsonpaket NuGet, sepertinya itu hanya metode perpanjangan IMvcCoreBuilder, bukan IMvcBuilder. Jadi itu digunakan seperti services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));.
infl3x

9

Di .net core 3 ini sekarang dimungkinkan dengan kelas bawaan di 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);

Untuk mengonfigurasi JsonStringEnumConverterdengan dekorasi atribut untuk properti tertentu:

using System.Text.Json.Serialization;

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

Jika Anda ingin selalu mengonversi enum sebagai string, letakkan atribut di enum itu sendiri.

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

9

Asp.Net Core 3 dengan System.Text.Json

public void ConfigureServices(IServiceCollection services)
{

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

    //...
 }

8

Kalau-kalau ada orang yang menemukan hal di atas tidak cukup, saya akhirnya puas dengan kelebihan ini:

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

Ini adalah solusi yang baik untuk kasus penggunaan saya saat ini: Saya tidak ingin mengubah default serializers dan saya memiliki masalah dalam menggunakan atribut, karena properti saya adalah tipe IList <EnumType>.
Dirk Brockhaus

5

Ini adalah pertanyaan lama tapi saya pikir saya akan berkontribusi untuk berjaga-jaga. Dalam proyek saya, saya menggunakan model terpisah untuk permintaan Json. Model biasanya memiliki nama yang sama dengan objek domain dengan awalan "Json". Model dipetakan menggunakan AutoMapper . Dengan meminta model json mendeklarasikan properti string yang merupakan enum pada kelas domain, AutoMapper akan memutuskan untuk presentasi stringnya.

Jika Anda bertanya-tanya, saya perlu model terpisah untuk kelas serial Json karena serializer inbuilt muncul dengan referensi melingkar sebaliknya.

Semoga ini bisa membantu seseorang.


Senang mengetahui bahwa fitur Automapper ;-) atribut [ScriptIgnore] akan menghapus referensi melingkar
ledragon

1
Oh Tidak tahu tentang atribut. Terima kasih! Apakah Anda akan menggunakannya pada Pocos Anda? Saya telah menggunakan definisi MetadataType untuk atribut Poco apa saja agar tetap bersih. Apakah atribut masih berfungsi melalui meta data?
Ales Potocnik Hahonina


1

Tidak yakin apakah ini masih relevan tetapi saya harus menulis langsung ke file json dan saya datang dengan berikut ini beberapa jawaban stackoverflow bersama-sama

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

Ini memastikan semua kunci json saya huruf kecil mulai sesuai dengan "aturan" json. Memformatnya dengan lekukan dan mengabaikan nol dalam output. Sedap dengan menambahkan StringEnumConverter itu mencetak enum dengan nilai string mereka.

Secara pribadi saya menemukan ini paling bersih yang bisa saya buat, tanpa harus mengotori model dengan anotasi.

pemakaian:

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

0

Saya telah mengumpulkan semua bagian dari solusi ini menggunakan Newtonsoft.Jsonperpustakaan. Ini memperbaiki masalah enum dan juga membuat penanganan kesalahan jauh lebih baik, dan berfungsi di layanan yang di-host IIS. Ini kode yang cukup banyak, sehingga Anda dapat menemukannya di GitHub di sini: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Anda harus menambahkan beberapa entri ke Web.configagar dapat berfungsi, Anda dapat melihat contoh file di sini: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config


0

Dan untuk VB.net saya menemukan karya-karya berikut:

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

Opsi yang sedikit lebih tahan di masa depan

Menghadapi pertanyaan yang sama, kami memutuskan bahwa kami membutuhkan versi khusus StringEnumConverteruntuk memastikan bahwa nilai enum kami dapat berkembang dari waktu ke waktu tanpa merusak secara serampangan pada sisi deserialisasi (lihat latar belakang di bawah). MenggunakanSafeEnumConverter bawah ini memungkinkan deserialization untuk menyelesaikan bahkan jika payload mengandung nilai untuk enum yang tidak memiliki definisi bernama, lebih dekat dengan bagaimana konversi int-to-enum akan bekerja.

Pemakaian:

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

atau

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

Sumber:

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

Latar Belakang

Ketika kami melihat menggunakan StringEnumConverter, masalah yang kami miliki adalah bahwa kami juga membutuhkan kepasifan untuk kasus ketika nilai enum baru ditambahkan, tetapi tidak setiap klien segera menyadari nilai baru. Dalam kasus ini, StringEnumConverterpaket dengan Newtonsoft JSON melempar JsonSerializationExceptionmirip dengan "Kesalahan mengkonversi nilai SomeString untuk mengetik EnumType" dan kemudian seluruh proses deserialisasi gagal. Ini adalah pemecah kesepakatan bagi kami, karena bahkan jika klien berencana mengabaikan / membuang nilai properti yang tidak dimengerti, ia masih harus mampu melakukan deserialisasi sisa muatan!


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

-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]  
);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.