Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用JSON.net将非数组JSON对象解析为数组_C#_Arrays_Json_Json.net_Deserialization - Fatal编程技术网

C# 使用JSON.net将非数组JSON对象解析为数组

C# 使用JSON.net将非数组JSON对象解析为数组,c#,arrays,json,json.net,deserialization,C#,Arrays,Json,Json.net,Deserialization,我正在使用一个外部API,它根据计数将属性作为数组或对象返回。处理这个问题的好方法是什么 作为数组返回: { "contacts": { "address": [ { "id": "47602070", "type": "Work", "street": "MyStreet", "city": "MyCity",

我正在使用一个外部API,它根据计数将属性作为数组或对象返回。处理这个问题的好方法是什么

作为数组返回:

{
    "contacts": {
        "address": [
            {
                "id": "47602070",
                "type": "Work",
                "street": "MyStreet",
                "city": "MyCity",
                "zip": "12345",
                "country": "USA"
            },
            {
                "id": "47732816",
                "type": "GPS",
                "street": "50.0,30.0"
            }
        ]
    }
}
{
    "contacts": {
        "address": {
            "id": "47602070",
            "type": "Work",
            "street": "MyStreet",
            "city": "MyCity",
            "zip": "12345",
            "country": "USA"
        }
    }
}
作为对象返回:

{
    "contacts": {
        "address": [
            {
                "id": "47602070",
                "type": "Work",
                "street": "MyStreet",
                "city": "MyCity",
                "zip": "12345",
                "country": "USA"
            },
            {
                "id": "47732816",
                "type": "GPS",
                "street": "50.0,30.0"
            }
        ]
    }
}
{
    "contacts": {
        "address": {
            "id": "47602070",
            "type": "Work",
            "street": "MyStreet",
            "city": "MyCity",
            "zip": "12345",
            "country": "USA"
        }
    }
}
我认为一种解决方法是使用自定义反序列化程序,为对象大小写返回长度为1的数组,为数组大小写返回默认反序列化,但我还不知道怎么做


我尝试将对象反序列化为一个数组,希望Json.net能帮我处理这个问题,但没有成功

一个定制的JSON.NET转换器可能会在这里实现这一点。没那么难

对于DateTime属性,可以按如下方式执行。只需使用自定义转换器装饰有问题的属性

[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
    [JsonProperty(PropertyName = "creation_date")]
    [JsonConverter(typeof(UnixDateTimeConverter))]
    public DateTime CreationDate { get; set; }
}
public class UnixDateTimeConverter : DateTimeConverterBase
{
    public override void WriteJson(JsonWriter writer, object value, 
                                   JsonSerializer serializer)
    { ...}

    public override void WriteJson(JsonWriter writer, object value, 
                                   JsonSerializer serializer)
    { ... } 
}  
JSON.NET提供了大部分管道。只需从基极转换器派生

[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
    [JsonProperty(PropertyName = "creation_date")]
    [JsonConverter(typeof(UnixDateTimeConverter))]
    public DateTime CreationDate { get; set; }
}
public class UnixDateTimeConverter : DateTimeConverterBase
{
    public override void WriteJson(JsonWriter writer, object value, 
                                   JsonSerializer serializer)
    { ...}

    public override void WriteJson(JsonWriter writer, object value, 
                                   JsonSerializer serializer)
    { ... } 
}  
您所要做的就是实现ReadJson(反序列化)和WriteJson(序列化)方法

您可以在此处找到完整的示例:

对于你的特殊问题,你需要更多的控制。请尝试以下类型的转换器:

public class Contact
{ 
   private List<Address> _addresses = new List<Address>();       
   public IEnumerable<Address> Addresses { get { return _addresses; }
}

public class ContactConverter : CustomCreationConverter<Contact>
{
    public override Contact Create(Type objectType)
    {
        return new Contact();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object 
        existingValue, JsonSerializer serializer)
    {
        var mappedObj = new Contact();

        // Parse JSON data here
        // ...

        return mappedObj;
    }
}
公共类联系人
{ 
私人名单

在这种情况下,在取消搜索时需要传递自定义转换器

Contact contact = 
    JsonConvert.DeserializeObject<Contact>(json, new ContactConverter());
联系人=
反序列化对象(json,new ContactConverter());

基于克里斯托夫·吉尔斯的观点,以下是我最终的做法

  • 创建自定义JSON转换器,以便始终将JSON解析为数组。如果JSON是非数组对象,则反序列化该对象并将其包装到数组中

  • 使用自定义转换器属性标记相应的属性

  • 自定义转换器

    public class JsonToArrayConverter<T> : CustomCreationConverter<T[]>
    {
        public override T[] Create(Type objectType)
        {
            // Default value is an empty array.
            return new T[0];
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object
            existingValue, JsonSerializer serializer)
        {
    
            if (reader.TokenType == JsonToken.StartArray)
            {
                // JSON object was an array, so just deserialize it as usual.
                object result = serializer.Deserialize(reader, objectType);
                return result;
            }
            else
            {
                // JSON object was not an arry, so deserialize the object
                // and wrap it in an array.
                var resultObject = serializer.Deserialize<T>(reader);
                return new T[] {resultObject};
            }
        }
    }
    
    公共类JsonToArrayConverter:CustomCreationConverter
    {
    公共重写T[]创建(类型objectType)
    {
    //默认值为空数组。
    返回新的T[0];
    }
    公共重写对象ReadJson(JsonReader,类型objectType,对象
    现有值,JsonSerializer序列化程序)
    {
    if(reader.TokenType==JsonToken.StartArray)
    {
    //JSON对象是一个数组,所以像往常一样反序列化它。
    对象结果=序列化程序。反序列化(读取器,对象类型);
    返回结果;
    }
    其他的
    {
    //JSON对象不是arry,因此反序列化该对象
    //并将其包装成一个数组。
    var resultObject=serializer.Deserialize(读取器);
    返回新的T[]{resultObject};
    }
    }
    }
    
    问题示例的数据结构

    public class Organisation
    {
        public Contacts contacts;
    }
    
    public class Address
    {
        public string id;
        public string street;
        public string city;
        public string type;
        public string zip;
        public string country;
    }
    
    public class Contacts
    {
        // Tell JSON.net to use the custom converter for this property.
        [JsonConverter(typeof(JsonToArrayConverter<Address>))]
        public Address[] address;
    }
    
    公共类组织
    {
    公众接触;
    }
    公共课堂演讲
    {
    公共字符串id;
    公众街;;
    公共字符串城市;
    公共字符串类型;
    公共字符串压缩;
    公共字符串国家;
    }
    公共类联系人
    {
    //告诉JSON.net为此属性使用自定义转换器。
    [JsonConverter(类型(JsonToArrayConverter))]
    公共广播[]地址;
    }
    
    注意:您可以使用普通的转换器,而不是使用
    CustomCreationConverter
    。例如,我使用的是这样的转换器:

    public class SingleToArrayConverter<T> : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var items = (IEnumerable<T>)value;
            if (value == null || !items.Any())
            {
                writer.WriteNull();
            }
            else if (items.Count() == 1)
            {
                serializer.Serialize(writer, items.ElementAt(0));
            }
            else
            {
                serializer.Serialize(writer, items);
            }
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (!CanConvert(objectType))
            {
                throw new NotSupportedException();
            }
    
            if (reader.TokenType == JsonToken.Null)
            {
                reader.Skip();
                return null;
            }
            else if (reader.TokenType == JsonToken.StartObject)
            {
                return new T[] { serializer.Deserialize<T>(reader) };
            }
            else
            {
                return serializer.Deserialize<T[]>(reader);
            }
        }
    
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(IEnumerable<T>);
        }
    }
    
    公共类SingleToArrayConverter:JsonConverter
    {
    公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
    {
    变量项=(IEnumerable)值;
    if(value==null | |!items.Any())
    {
    WriteNull();
    }
    else if(items.Count()==1)
    {
    serializer.Serialize(writer,items.ElementAt(0));
    }
    其他的
    {
    序列化器。序列化(编写器、项);
    }
    }
    公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
    {
    如果(!CanConvert(对象类型))
    {
    抛出新的NotSupportedException();
    }
    if(reader.TokenType==JsonToken.Null)
    {
    reader.Skip();
    返回null;
    }
    else if(reader.TokenType==JsonToken.StartObject)
    {
    返回新的T[]{serializer.Deserialize(reader)};
    }
    其他的
    {
    返回序列化程序。反序列化(读取器);
    }
    }
    公共覆盖布尔CanConvert(类型objectType)
    {
    返回objectType==typeof(IEnumerable);
    }
    }
    
    感谢您的全面投入。从您的示例中,我得到了成功,并发布了最终结果。