Pytanie Jak deserializować właściwość JSON, która może być dwoma różnymi typami danych za pomocą Json.NET


Używam Json.NET do projektu, nad którym pracuję. Z zewnętrznego API otrzymuję JSON z właściwościami, które są obiektami, ale gdy są puste, przekazywana jest wartość "false".

Na przykład:

data: {
    supplier: {
        id: 15,
        name: 'TheOne'
    }
}

Może to być:

data: {
    supplier: false
}

Jak zdefiniować właściwość dostawcy, aby dostawca został przekształcony z postaci szeregowej na obiekt dostawcy lub wartość zerową.

Teraz mam:

public class Data {
   [JsonProperty("supplier")]
   public SupplierData Supplier { get; set; }
}
public class SupplierData {
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("name")]
    public string Name { get; set; }
}

Ale teraz, gdy próbuje się deserializować, gdy dostawca ma wartość "false", nie działa. Chciałbym, aby właściwość dostawcy była pusta, gdy wartość JSON jest "fałsz".

Mam nadzieję, że ktoś wie, jak to zrobić. Dzięki.


14
2017-12-06 19:37


pochodzenie


Możesz utworzyć niestandardowy konwerter JSON i przeczytać JSON. Zobacz ten link: stackoverflow.com/questions/19307752/... - Poornima


Odpowiedzi:


Można to rozwiązać, wykonując zwyczaj JsonConverter dla Twojego SupplierData klasa. Oto, jak może wyglądać konwerter:

class SupplierDataConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(SupplierData));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return token.ToObject<SupplierData>();
        }
        return null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

Aby z niego skorzystać, wystarczy dodać [JsonConverter] atrybut do Supplier własność w twoim Data klasa taka jak ta:

public class Data
{
    [JsonProperty("supplier")]
    [JsonConverter(typeof(SupplierDataConverter))]
    public SupplierData Supplier { get; set; }
}

Poniżej znajduje się demonstracja konwertera w akcji. Zauważ, że wersja demonstracyjna zakłada, że ​​masz jakiś obiekt zawierający obiekt data własność, ponieważ JSON w twoim pytaniu nie może stać samodzielnie. Zdefiniowałem klasę o nazwie RootObject w tym celu:

public class RootObject
{
    [JsonProperty("data")]
    public Data Data { get; set; }
}

Aktualny kod demo:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""data"": 
            {
                ""supplier"": 
                {
                    ""id"": 15,
                    ""name"": ""TheOne""
                }
            }
        }";

        Console.WriteLine("--- first run ---");
        RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
        DumpSupplier(obj.Data.Supplier);

        json = @"
        {
            ""data"": 
            {
                ""supplier"": false
            }
        }";

        Console.WriteLine("--- second run ---");
        obj = JsonConvert.DeserializeObject<RootObject>(json);
        DumpSupplier(obj.Data.Supplier);
    }

    static void DumpSupplier(SupplierData supplier)
    {
        if (supplier != null)
        {
            Console.WriteLine("Id: " + supplier.Id);
            Console.WriteLine("Name: " + supplier.Name);
        }
        else
        {
            Console.WriteLine("(null)");
        }
        Console.WriteLine();
    }
}

A oto wynik z powyższego:

--- first run ---
Id: 15
Name: TheOne

--- second run ---
(null)

23
2018-01-03 02:19



Miałem podobny przypadek, w którym właściwość była albo obiektem, albo pustą tablicą. Zwykle jest to zła decyzja, aby API złamało się tak bez wersji, ale jest to wystarczająco czyste rozwiązanie. Dzięki! - Ran Sagy