【问题标题】:How to deserialize a JSON property that can be two different data types using Json.NET如何使用 Json.NET 反序列化可以是两种不同数据类型的 JSON 属性
【发布时间】:2013-12-24 07:00:54
【问题描述】:

我正在将 Json.NET 用于我正在进行的项目。 从外部 API,我收到带有对象属性的 JSON,但是当它们为空时,传递了“假”。

例如:

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”时,我希望 Supplier 属性为 null。

我希望有人知道如何做到这一点。谢谢。

【问题讨论】:

标签: c# json serialization json.net


【解决方案1】:

这可以通过为您的 SupplierData 类创建自定义 JsonConverter 来解决。以下是转换器的外观:

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 属性中添加一个 [JsonConverter] 属性到您的 Data 类中,如下所示:

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

下面是转换器的演示。请注意,该演示假定您有某种包含 data 属性的对象,因为您问题中的 JSON 不能独立存在。为此,我定义了一个名为 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)

【讨论】:

  • 我也遇到过类似的情况,其中一个属性要么是一个对象,要么是一个空数组。如果 API 在没有版本控制的情况下像这样中断,这主要是一个糟糕的决定,但对于它来说,这是一个足够干净的解决方案。谢谢!
  • 我怎样才能两者兼得?我希望两者都被转换 ""supplier"": { ""id"": 15, ""name"": ""TheOne"" } 和 json = @" { ""data"": { ""supplier "": 假 } }";
  • @Decoder94 也许你可以发一个new question 并告诉我们你想更详细地做什么?如果需要,您可以链接回此问题/答案以提供上下文。
猜你喜欢
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 2014-03-16
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多