Newtonsoft.json: Pengonversi Enum - Penanganan Nilai Tidak Diketahui

Dibuat pada 28 Jun 2017  ·  4Komentar  ·  Sumber: JamesNK/Newtonsoft.Json

Hai Newtonsoft,
Saya tidak yakin apakah ini bug atau permintaan fitur, tetapi begini:
Saya sedang membangun aplikasi yang terhubung ke layanan pihak ketiga. Di banyak tempat, layanan mengembalikan konstanta string yang lebih baik dapat direpresentasikan sebagai Enum. Nilai baru tidak sering ditambahkan, tetapi ditambahkan sesekali, dan ketika itu terjadi, saya tidak ingin kode saya mulai mogok. Saya hanya ingin dapat melakukan deserialize enum yang tidak dikenal sebagai nilai lain.

Saya sudah mencoba menggunakan DefaultValue dan metode lain tetapi tidak berhasil. StackOverflow tampaknya menunjukkan bahwa Anda harus menggulung konverter Anda sendiri untuk mewujudkannya, tetapi itu sepertinya berlebihan.

Saya perhatikan bahwa JsonSerializerSettings memiliki banyak properti yang mengontrol bagaimana berbagai tipe dideserialisasi tetapi tidak ada yang ada hubungannya dengan Enums.

Mungkin saya melakukan sesuatu yang salah, tetapi jika tidak, saya mengusulkan untuk menambahkan anggota berikut:
JsonSerializerSettings.UnknownEnumValueHandling dengan opsi:
ThrowException - Perilaku default saat ini - pengecualian dilemparkan.
Abaikan - nilai enum diabaikan.
UseDefault - Nilai default enum digunakan. Ini harus mengambil nilai dari atribut DefaultValue atau secara bergantian, mungkin atribut UnknownValue baru yang dapat diterapkan ke anggota atau enum.

Akan lebih bagus jika bisa mengonversi Enum yang memiliki garis bawah dalam nilai. Sebagai contoh,

in_progress (string) -> Status.InProgress (enum)

Di bawah ini adalah kode yang memberikan contoh kecil dari masalah.

Jenis sumber/tujuan

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ComponentModel;

namespace ConsoleApp7 {
    class Program {
        static void Main(string[] args) {
            var Contents = new[]{

                @"{""Status"": ""Open""}"
                , @"{""Status"": ""open""}"
                , @"{""Status"": ""closed""}"
                , @"{""Status"": ""Pizza""}"
            };


            var Settings = new Newtonsoft.Json.JsonSerializerSettings();
            Settings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Populate;
            Settings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.

            foreach(var item in Contents) {
                try {
                    var Matter = Newtonsoft.Json.JsonConvert.DeserializeObject<Matter>(item, Settings);
                } catch (Exception ex) {

                }
            }


        }
    }

    [DefaultValue(MatterStatus.Unknown)]
    public enum MatterStatus {
        Unknown,
        Open,
        Closed,
        Pending,
    }

    public class Matter {
        [DefaultValue(MatterStatus.Unknown)]
        public MatterStatus Status { get; set; }
    }

}

Komentar yang paling membantu

Ada pembaruan? Ini cukup berguna bagi saya. Jika bisa, saya akan menerapkan ini sambil menyelesaikan masalah saya di sini di #1597

Semua 4 komentar

Saya akhirnya mencapai skenario yang sangat mirip baru-baru ini. Saya memiliki layanan web yang mengembalikan json yang berisi array string, dan masing-masing string tersebut sesuai dengan nilai enum. Namun, program klien yang menggunakan titik akhir API itu hanya perlu mengetahui sebagian kecil dari string tersebut, yang dengan mudah direpresentasikan sebagai enum dalam kode saya (menggunakan [EnumMember(Value = "actual_string_representation")] untuk mendefinisikan representasi string dari enum). StringEnumConverter bawaan mengeluarkan pengecualian setiap kali mencapai salah satu nilai yang tidak ditentukan, yang tidak ideal.

Solusi saya saat ini adalah dengan menggunakan kelas yang disebut TolerantEnumConverter , dan menggunakannya untuk deserialize array dengan atribut [JsonProperty(PropertyName = "my_enums", ItemConverterType = typeof(TolerantEnumConverter))]

Kode untuk TolerantEnumConverter dapat ditemukan di sini:

https://Gist.github.com/gubenkoved/999eb73e227b7063a67a50401578c3a7

Saya setuju dengan Anda bahwa menggunakan ini hanya sementara, itu cukup berlebihan karena kebanyakan hanya menggunakan kode dari StringEnumConverter .

Agar fungsionalitas ini dapat dibangun ke dalam Json.Net, saya pikir StringEnumConverter perlu dimodifikasi untuk menerima parameter "UnknownEnumValueHandling" dan memilih nilai default. TolerantEnumConverter atas berisi beberapa kode yang cukup bagus yang dapat disambung - terutama dalam cara memilih nilai default:

Jika enum adalah nullable, maka null digunakan sebagai default.

Jika salah satu enum bernama "Tidak Diketahui", mereka digunakan sebagai default.

Jika tidak, enum pertama digunakan sebagai default. Ini harus dimodifikasi untuk juga mempertimbangkan dan memprioritaskan atribut [DefaultValue] .

Hal lain: Bagaimana pengaturan UnknownEnumValueHandling.Ignore akan ditafsirkan? Saya tidak berpikir itu benar-benar mungkin untuk "Mengabaikan" enum, karena itu telah diatur ke sesuatu selama deserialisasi.

Akan lebih bagus jika bisa mengonversi Enum yang memiliki garis bawah dalam nilai. Misalnya, in_progress (string) -> Status.InProgress (enum)

Jika saya mengerti apa yang Anda coba lakukan dengan benar, ini sudah dimungkinkan dengan meletakkan atribut [EnumMember] atas tempat enum didefinisikan, seperti:

enum SomeEnum {
    [EnumMember(Value = "some_body")]
    SomeBody,
    [EnumMember(Value = "once_told_me")]
    OnceToldMe,
    [EnumMember(Value = "that_enums")]
    ThatEnums,
    [EnumMember(Value = "were_gonna_role_me")]
    WereGonnaRollMe
}

StringEnumConverter akan mendeteksi atribut [EnumMember] dan mencari nilai string yang ditentukan di sana, alih-alih menggunakan representasi string default dari enum.

Adakah pembaruan tentang masalah ini? Apakah itu bahkan dianggap? Masih harus mewarisi dari StringEnumConverter untuk mendukung DefaultValue.

Ada pembaruan? Ini cukup berguna bagi saya. Jika bisa, saya akan menerapkan ini sambil menyelesaikan masalah saya di sini di #1597

Apakah halaman ini membantu?
0 / 5 - 0 peringkat