Katakanlah saya memiliki cuplikan json kecil ini:

{
  "Type": "Bar",
  "BarOnly": "This is a string readable when deserialized to the Bar class only, as declared in my type key"
}

Saya juga memiliki tiga kelas ini:

public class Base
{
    public enum SampleEnum
    {
        Bar,
        Baz,
    }

    public SampleEnum Type
    {
        get;
        set;
    }
}

public class Bar : Base
{
    public string BarOnly
    {
        get;
        set;
    }
}

public class Baz : Base
{
    public string BazOnly
    {
        get;
        set;
    }
}

Berdasarkan properti Type di json snippet, saya ingin deserialize ke Bar atau Baz.
Ide pertama saya adalah pertama-tama deserialize ke kelas Base, dan kemudian gunakan tipenya dan pernyataan switch untuk deserialize JSON lagi ke kelas masing-masing. (Menggunakan Newtonsoft.Json)

var type = JsonConvert.DeserializeObject<Base>(json).Type;
string message = "";
switch (type)
{
    case (Base.SampleEnum.Bar):
        message = JsonConvert.DeserializeObject<Bar>(json).BarOnly;
        break;
    case (Base.SampleEnum.Baz):
        message = JsonConvert.DeserializeObject<Baz>(json).BazOnly;
        break;
}
Console.WriteLine(message);

Tak perlu dikatakan bahwa proses ini sangat berlebihan, membosankan dan, karena pernyataan switch dikodekan dengan keras, sama sekali tidak "dinamis".
Ide lain adalah menggunakan kelas generik sebagai kelas dasar dan meneruskan tipe kelas sebenarnya yang harus di-deserialize, tetapi kemudian saya berakhir dengan pernyataan switch yang sama untuk mencari tahu seperti apa kelas itu.
Karena Anda tidak dapat memetakan enum ke tipe kelas, saya juga berpikir untuk menggunakan Kamus untuk memetakan kemungkinan nilai enum ke rekan kelasnya; ini masih membuat proses pemetaan sulit dikodekan.
Apakah ada cara agar saya dapat secara dinamis membuat kelas yang sesuai untuk dideserialisasi berdasarkan properti tipe objek json?

EDIT: Tampaknya ada beberapa kebingungan tentang bagaimana ini seharusnya digunakan dan bagaimana data diambil; izinkan saya memberikan beberapa informasi latar belakang.
Saya mengulangi direktori dengan banyak file spreadsheet yang berbeda, sebagian besar file CSV dan XML. Masing-masing feed ini memiliki "file meta", yang menjelaskan cara memproses kontennya. Ini termasuk checksum, pembatas dan informasi lainnya. Mereka juga mendeklarasikan jenis file induk mereka (CSV, XML dll). Oleh karena itu, mereka berbagi banyak properti umum (seperti kelas Base dalam contoh saya), tetapi juga memiliki kumpulan properti mereka sendiri. Mereka berasal dari kelas abstrak yang mengharuskan mereka untuk mengimplementasikan fungsi yang mengembalikan instance kelas pemrosesan feed yang sesuai, yang diinisialisasi dengan nilai langsung dari dalam kelas meta. Saya harap ini masuk akal.

0
SearchingSolutions 19 April 2020, 21:03

1 menjawab

Jawaban Terbaik

@OguzOzgul komentar benar. Saya telah melakukan ini berkali-kali untuk objek yang disusun dengan antarmuka yang perlu diserialisasi dan dideserialisasi.

Lihat TypeNameHandling untuk Newtonsoft: https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling. htm

File json Anda akan terlihat sedikit berbeda:

{
    "$type": "SomeNamespace.Bar",
    "BarOnly": "This is a string readable when deserialized to the Bar class only, as declared in my type key"
}

Jika Anda menggunakan

new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
}

Selama serialisasi, itu akan menambahkan nama tipe lengkap dari semua objek untuk memastikan newtonsoft tahu apa tipenya selama deserialisasi (mengingat Anda menggunakan pengaturan yang sama saat itu). Dengan begitu Anda tidak perlu menulis kode kustom Anda sendiri untuk pendeteksian jenis.

1
Davey van Tilburg 20 April 2020, 17:41