web-dev-qa-db-ja.com

Json.NETを使用して2つの異なるデータ型になる可能性があるJSONプロパティをデシリアライズする方法

作業中のプロジェクトにJson.NETを使用しています。外部APIから、オブジェクトであるプロパティを持つJSONを受信して​​いますが、それらが空の場合は「false」が渡されます。

例えば:

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

次のことも考えられます。

data: {
    supplier: false
}

サプライヤがサプライヤオブジェクトまたはnullに逆シリアル化されるように、サプライヤプロパティを定義するにはどうすればよいですか。

今私は持っています:

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

しかし、サプライヤに「false」の値があるときに逆シリアル化しようとすると、失敗します。 JSON値が「false」の場合、サプライヤープロパティをnullにしたいのですが。

誰かがこれを行う方法を知っていることを願っています。ありがとう。

25
Marc Selman

これは、JsonConverterクラスにカスタム SupplierData を作成することで解決できます。コンバーターは次のようになります。

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

これを使用するには、次のようにSupplierクラスのDataプロパティに[JsonConverter]属性を追加するだけです。

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

以下は、コンバーターの動作のデモです。質問のJSONはそれ自体では成り立たないため、デモではdataプロパティに何らかのオブジェクトが含まれていると想定しています。この目的のために、RootObjectというクラスを定義しました。

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

実際のデモコードは次のとおりです。

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

そして、これは上記の出力です:

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

--- second run ---
(null)
34
Brian Rogers