Deserializacja danych z JSONa - trzeba użyć dynamic?

0

C# jest (zazwyczaj) statycznie typowany. JSON dynamicznie. Dlatego deserializacja z JSONa do C# - potrzebna, gdy np. kod C# ma korzystać z zewnetrznego API - może stwarzać problemy.

Przykład. WooCommerce ma wystawione API, za pomocą którego można m.in. pobrać / wysłać dane produktu/ów. Obiekt określający produkt zawiera m.in. tablicę meta-danych, które są zdefiniowane w sposób następujący:

Attribute Type Description
id integer Meta ID. READ-ONLY
key string Meta key.
value string Meta value.

Model danych, do którego to deserializować, wydaje się być prosty?

public class Product
{
    /* ...
       ... inne pola
       ... */

    public List<ProductMeta> meta_data {get; set;}
}

public class ProductMeta
{
    public ulong id {get; set;}
    public string key {get; set;}
    public string value {get; set;}
}

Gdzie tam. value zazwyczaj jest stringiem, ale nie zawsze. Niektóre wtyczki mają w nosie dokumentację i w polu value wysyłają obiekt JSONowy, a nie stringa. Dlatego public string value grozi wyjątkami podczas deserializacji.

Gdyby to miał być obiekt JSONowy taki albo inny, to można by jeszcze zastosować dziedziczenie... Ale string albo obiekt?!

Jedyny pomysł, jaki mi przychodzi do głowy, to albo public object value {get; set;}, albo public dynamic value {get; set;}.

Rzeczywiście trzeba w tego rodzaju sytuacjach użyć dynamic, czy jest jakieś lepsze rozwiązanie, którego nie widzę?

1

A czemu json miałby się nie zdeserializowac do stringa?

0
kzkzg napisał(a):

A czemu json miałby się nie zdeserializowac do stringa?

{
    "id": 1234,
    /* inne pola */
    "meta_data": [
        {
            "id": 4321,
            "key": "jakiśKlucz",
            "value": "jakaśWartość"
        },
        {
            "id": 4141,
            "key": "denerwującyKlucz",
            "value": {
                "no": "to",
                "jednak": "się",
                "do": "stringa",
                "nie": "zdeserializuje"
            }
        }
    ]
}
2

Najłatwiej będzie użyć typu object i mając już zdeserializowaną odpowiedź zdecydować co robić z nią dalej.
Użycie dynamic w tym kontekście nie będzie się różnić niczym od object.
Kolejną opcją mogłoby być wykorzystanie JObject i sprawdzenie zawartości odpowiedzi oraz jej ewentualna konwersja przed deserializacją (przykład z dokumentacji który niekoniecznie odpowiada problemowi ale pokazujący czego użyć https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm). Ten scenariusz jednak wygląda na tyle prosto że najmniej skomplikowany sposób będzie najlepszy.

0

A jak po zdeserializowaniu chcesz tego używać?

Korzystając z biblioteki Newtonsoft.Json dało się napisać jakieś konwertery (albo coś podobnego, nie pamiętam już nazewnictwa), które albo na podstawie pola oznaczającego typ, zdeserializują do konkretnego typu po stronie .NET, albo samemu rzeźbić i nawet na podstawie istnienia konkretnych pól w JSONie deserializować do konkretnych typów w .NET.

Tym sposobem mógłbyś mieć jakieś klasy StringValue i SomethingValue dziedziczące po czymś bazowym i deserializować do konkretnego typu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1