如何使用Json.NET反序列化可以是两种不同数据类型的JSON属性

时间:2021-09-22 16:57:07

I'm using Json.NET for a project I'm working on. From an external API, I am receiving JSON with properties that are objects, but when they are empty 'false' is passed.

我使用Json。我正在做一个项目。从外部API中,我接收的是具有对象属性的JSON,但当它们为空时,“false”就会被传递。

For example:

例如:

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

Could also be:

也可以:

data: {
    supplier: false
}

How should I define the supplier property so that the supplier will be deserialized to a Supplier object or null.

如何定义供应商属性,以便将供应商反序列化为供应商对象或null。

Right now I have:

现在我有:

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

But now when trying to deserialize when supplier has a value of 'false' it fails. I would like the Supplier property to be null when the JSON value is 'false'.

但是现在当供应商的值为“false”时,尝试反序列化时失败了。当JSON值为“false”时,我希望供应商属性为null。

I hope someone knows how to do this. Thanks.

我希望有人知道怎么做。谢谢。

1 个解决方案

#1


23  

This can be solved by making a custom JsonConverter for your SupplierData class. Here is what the converter might look like:

这可以通过为您的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);
    }
}

To use it, all you would need to do is add a [JsonConverter] attribute to the Supplier property in your Data class like this:

要使用它,您需要做的就是在您的数据类中添加一个[JsonConverter]属性:

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

Below is a demonstration of the converter in action. Note that the demo assumes you have some kind of containing object for the data property, since the JSON in your question can't stand on its own. I defined a class called RootObject for this purpose:

下面是转换器工作的演示。注意,演示假定您有某种包含数据属性的对象,因为问题中的JSON不能独立存在。我为这个目的定义了一个名为RootObject的类:

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

The actual demo code follows:

实际的演示代码如下:

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

And here is the output from the above:

这是上面的输出:

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

--- second run ---
(null)

#1


23  

This can be solved by making a custom JsonConverter for your SupplierData class. Here is what the converter might look like:

这可以通过为您的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);
    }
}

To use it, all you would need to do is add a [JsonConverter] attribute to the Supplier property in your Data class like this:

要使用它,您需要做的就是在您的数据类中添加一个[JsonConverter]属性:

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

Below is a demonstration of the converter in action. Note that the demo assumes you have some kind of containing object for the data property, since the JSON in your question can't stand on its own. I defined a class called RootObject for this purpose:

下面是转换器工作的演示。注意,演示假定您有某种包含数据属性的对象,因为问题中的JSON不能独立存在。我为这个目的定义了一个名为RootObject的类:

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

The actual demo code follows:

实际的演示代码如下:

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

And here is the output from the above:

这是上面的输出:

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

--- second run ---
(null)