Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.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# 当对象类属性不需要数据时,如何完全防止JSONVERT反序列化对象错误?_C#_Json_Json Deserialization - Fatal编程技术网

C# 当对象类属性不需要数据时,如何完全防止JSONVERT反序列化对象错误?

C# 当对象类属性不需要数据时,如何完全防止JSONVERT反序列化对象错误?,c#,json,json-deserialization,C#,Json,Json Deserialization,我经常使用为Json数据响应创建C#类,我经常发现,如果插入到类生成器中的Json的特定快照缺少数据,那么我就没有正确的类属性来处理数据,这可能导致未处理的反序列化错误。 以下是一个例子: "toasts": { "total_count": 1, "count": 1, "auth_toast": false, "items": [ { "uid": 3250810,

我经常使用为Json数据响应创建C#类,我经常发现,如果插入到类生成器中的Json的特定快照缺少数据,那么我就没有正确的类属性来处理数据,这可能导致未处理的反序列化错误。 以下是一个例子:

    "toasts": {
        "total_count": 1,
        "count": 1,
        "auth_toast": false,
        "items": [
            {
                "uid": 3250810,
                "user": {
                    "uid": 3250810,
                    "user_name": "jdoe",
                    "first_name": "Jane",
                    "last_name": "Doe",
                    "bio": "",
                    "location": "",
                    "relationship": "friends",
                    "user_avatar": "",
                    "account_type": "user",
                    "venue_details": [
                    ],
                    "brewery_details": [
                    ]
                },
                "like_id": 488764809,
                "like_owner": false,
                "created_at": "Fri, 16 Mar 2018 20:35:44 +0000"
            }
        ]
    },
在该示例中,“场馆详细信息:”下没有数据,因此未发现任何属性,生成的C类如下所示:

    public class ViewCheckinID_Toasts
    {
        public int total_count { get; set; }
        public int count { get; set; }
        public bool auth_toast { get; set; }
        public List<ViewCheckinID_Item2> items { get; set; }
    }


    public class ViewCheckinID_Item2
    {
        public int uid { get; set; }
        public ViewCheckinID_User2 user { get; set; }
        public int like_id { get; set; }
        public bool like_owner { get; set; }
        public string created_at { get; set; }
    }

public class ViewCheckinID_User2
{
    public int uid { get; set; }
    public string user_name { get; set; }
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string bio { get; set; }
    public string location { get; set; }
    public string relationship { get; set; }
    public string user_avatar { get; set; }
    public string account_type { get; set; }
    public object[] venue_details { get; set; }
    public object[] brewery_details { get; set; }
    public string user_link { get; set; }
}
所以现在它不是一个数组,而是一个字符串属性。最终导致以下内容的反序列化错误:

JsonSerializationException:无法将当前JSON对象(例如{“名称”:“值”})反序列化为类型“System.object[]”,因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。 若要修复此错误,请将JSON更改为JSON数组(例如[1,2,3]),或更改反序列化类型,使其成为可以从JSON对象反序列化的正常.NET类型(例如,不是integer之类的基元类型,也不是数组或列表之类的集合类型)。还可以将JsonObjectAttribute添加到类型中,以强制它从JSON对象反序列化。 路径“response.checkin.toasts.items[0]。用户。场馆详细信息。场馆id”,第143行,位置20

如果我使用新的Json并再次通过C#classes生成器运行它,那么我会得到这个已修复的属性,然后错误就会消失:

    public class ViewCheckinID_User2
    {
        public int uid { get; set; }
        public string user_name { get; set; }
        public string first_name { get; set; }
        public string last_name { get; set; }
        public string bio { get; set; }
        public string location { get; set; }
        public string relationship { get; set; }
        public string user_avatar { get; set; }
        public string account_type { get; set; }
        public ViewCheckinID_VenueDetails venue_details { get; set; }
        public object[] brewery_details { get; set; }
        public string user_link { get; set; }
    }

    public class ViewCheckinID_VenueDetails
    {
        public int venue_id { get; set; }
    }
我想做的是能够抵御这个错误。我一直在使用这些帮助器类进行反序列化,但它不能处理这种情况:

    string strFileName = @"C:\Users\rick\Documents\files\dev\Explorer\DataModels\ricke_Checkin_View_CheckinID.json";


    var resolver = new DefaultContractResolver(); // Cache for performance
    var Serializersettings = new JsonSerializerSettings
    {
        ContractResolver = resolver,
        Converters = { new IgnoreUnexpectedArraysConverter(resolver) },
    };
    ViewCheckinID_RootObject checkinInfo = JsonConvert.DeserializeObject<ViewCheckinID_RootObject>(File.ReadAllText(strFileName), Serializersettings);

    public class IgnoreUnexpectedArraysConverter<T> : IgnoreUnexpectedArraysConverterBase
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(T).IsAssignableFrom(objectType);
        }
    }

    public class IgnoreUnexpectedArraysConverter : IgnoreUnexpectedArraysConverterBase
    {
        readonly IContractResolver resolver;

        public IgnoreUnexpectedArraysConverter(IContractResolver resolver)
        {
            if (resolver == null)
                throw new ArgumentNullException();
            this.resolver = resolver;
        }

        public override bool CanConvert(Type objectType)
        {
            if (objectType.IsPrimitive || objectType == typeof(string))
                return false;
            return resolver.ResolveContract(objectType) is JsonObjectContract;
        }
    }

    public abstract class IgnoreUnexpectedArraysConverterBase : JsonConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var contract = serializer.ContractResolver.ResolveContract(objectType);
            if (!(contract is JsonObjectContract))
            {
                throw new JsonSerializationException(string.Format("{0} is not a JSON object", objectType));
            }

            do
            {
                if (reader.TokenType == JsonToken.Null)
                    return null;
                else if (reader.TokenType == JsonToken.Comment)
                    continue;
                else if (reader.TokenType == JsonToken.StartArray)
                {
                    var array = JArray.Load(reader);
                    if (array.Count > 0)
                        throw new JsonSerializationException(string.Format("Array was not empty."));
                    return existingValue ?? contract.DefaultCreator();
                }
                else if (reader.TokenType == JsonToken.StartObject)
                {
                    // Prevent infinite recursion by using Populate()
                    existingValue = existingValue ?? contract.DefaultCreator();
***                 serializer.Populate(reader, existingValue);
                    return existingValue;
                }
                else
                {
                    throw new JsonSerializationException(string.Format("Unexpected token {0}", reader.TokenType));
                }
            }
            while (reader.Read());
            throw new JsonSerializationException("Unexpected end of JSON.");
        }

        public override bool CanWrite { get { return false; } }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }


    public class SingleValueArrayConverter<T> : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object retVal = new Object();
            if (reader.TokenType == JsonToken.StartObject)
            {
                T instance = (T)serializer.Deserialize(reader, typeof(T));
                retVal = new List<T>() { instance };
            } else if (reader.TokenType == JsonToken.StartArray) {
                retVal = serializer.Deserialize(reader, objectType);
            }
            return retVal;
        }

        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    }
string strFileName=@“C:\Users\rick\Documents\files\dev\Explorer\DataModels\ricke\u Checkin\u View\u CheckinID.json”;
var resolver=new DefaultContractResolver();//性能缓存
var Serializersettings=new JsonSerializerSettings
{
合同解析程序=解析程序,
转换器={new IgnoreUnexpectedArraysConverter(解析器)},
};
ViewCheckinID\u RootObject checkinInfo=JsonConvert.DeserializeObject(File.ReadAllText(strFileName),SerializeSettings);
公共类IgnoreUnexpectedArraysConverter:IgnoreUnexpectedArraysConverterBase
{
公共覆盖布尔CanConvert(类型objectType)
{
返回typeof(T).IsAssignableFrom(objectType);
}
}
公共类IgnoreUnexpectedArraysConverter:IgnoreUnexpectedArraysConverterBase
{
只读IContractResolver解析器;
公共信号意外阵列转换器(IContractResolver resolver)
{
if(解析器==null)
抛出新ArgumentNullException();
this.resolver=解析器;
}
公共覆盖布尔CanConvert(类型objectType)
{
if(objectType.IsPrimitive | | objectType==typeof(string))
返回false;
返回解析器。ResolveContract(objectType)为JsonObjectContract;
}
}
公共抽象类IgnoreUnexpectedArraysConverterBase:JsonConverter
{
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var contract=serializer.ContractResolver.ResolveContract(objectType);
如果(!(合同为JsonObjectContract))
{
抛出新的JsonSerializationException(string.Format(“{0}不是JSON对象”,objectType));
}
做
{
if(reader.TokenType==JsonToken.Null)
返回null;
else if(reader.TokenType==JsonToken.Comment)
继续;
else if(reader.TokenType==JsonToken.StartArray)
{
var数组=JArray.Load(读卡器);
如果(array.Count>0)
抛出新的JsonSerializationException(string.Format(“数组不是空的”);
返回现有值??contract.DefaultCreator();
}
else if(reader.TokenType==JsonToken.StartObject)
{
//使用Populate()防止无限递归
existingValue=existingValue??contract.DefaultCreator();
***序列化程序。填充(读取器,现有值);
返回现有值;
}
其他的
{
抛出新的JsonSerializationException(string.Format(“意外标记{0}”,reader.TokenType));
}
}
while(reader.Read());
抛出新的JsonSerializationException(“JSON意外结束”);
}
公共重写bool可以写入{get{return false;}}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
}
公共类SingleValueArrayConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
object retVal=新对象();
if(reader.TokenType==JsonToken.StartObject)
{
反序列化(reader,typeof(T));
retVal=new List(){instance};
}else if(reader.TokenType==JsonToken.StartArray){
retVal=序列化程序。反序列化(读取器,对象类型);
}
返回返回;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回true;
}
}
如果在帮助器类中看到IgnoreUnexpectedArraysConver
    string strFileName = @"C:\Users\rick\Documents\files\dev\Explorer\DataModels\ricke_Checkin_View_CheckinID.json";


    var resolver = new DefaultContractResolver(); // Cache for performance
    var Serializersettings = new JsonSerializerSettings
    {
        ContractResolver = resolver,
        Converters = { new IgnoreUnexpectedArraysConverter(resolver) },
    };
    ViewCheckinID_RootObject checkinInfo = JsonConvert.DeserializeObject<ViewCheckinID_RootObject>(File.ReadAllText(strFileName), Serializersettings);

    public class IgnoreUnexpectedArraysConverter<T> : IgnoreUnexpectedArraysConverterBase
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(T).IsAssignableFrom(objectType);
        }
    }

    public class IgnoreUnexpectedArraysConverter : IgnoreUnexpectedArraysConverterBase
    {
        readonly IContractResolver resolver;

        public IgnoreUnexpectedArraysConverter(IContractResolver resolver)
        {
            if (resolver == null)
                throw new ArgumentNullException();
            this.resolver = resolver;
        }

        public override bool CanConvert(Type objectType)
        {
            if (objectType.IsPrimitive || objectType == typeof(string))
                return false;
            return resolver.ResolveContract(objectType) is JsonObjectContract;
        }
    }

    public abstract class IgnoreUnexpectedArraysConverterBase : JsonConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var contract = serializer.ContractResolver.ResolveContract(objectType);
            if (!(contract is JsonObjectContract))
            {
                throw new JsonSerializationException(string.Format("{0} is not a JSON object", objectType));
            }

            do
            {
                if (reader.TokenType == JsonToken.Null)
                    return null;
                else if (reader.TokenType == JsonToken.Comment)
                    continue;
                else if (reader.TokenType == JsonToken.StartArray)
                {
                    var array = JArray.Load(reader);
                    if (array.Count > 0)
                        throw new JsonSerializationException(string.Format("Array was not empty."));
                    return existingValue ?? contract.DefaultCreator();
                }
                else if (reader.TokenType == JsonToken.StartObject)
                {
                    // Prevent infinite recursion by using Populate()
                    existingValue = existingValue ?? contract.DefaultCreator();
***                 serializer.Populate(reader, existingValue);
                    return existingValue;
                }
                else
                {
                    throw new JsonSerializationException(string.Format("Unexpected token {0}", reader.TokenType));
                }
            }
            while (reader.Read());
            throw new JsonSerializationException("Unexpected end of JSON.");
        }

        public override bool CanWrite { get { return false; } }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }


    public class SingleValueArrayConverter<T> : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object retVal = new Object();
            if (reader.TokenType == JsonToken.StartObject)
            {
                T instance = (T)serializer.Deserialize(reader, typeof(T));
                retVal = new List<T>() { instance };
            } else if (reader.TokenType == JsonToken.StartArray) {
                retVal = serializer.Deserialize(reader, objectType);
            }
            return retVal;
        }

        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    }
{
   "toasts":[
      {
         "total_count":1,
         "count":1,
         "auth_toast":false,
         "items":[
            {
               "uid":3250810,
               "user":{
                  "uid":3250810,
                  "user_name":"jdoe",
                  "first_name":"Jane",
                  "last_name":"Doe",
                  "bio":"",
                  "location":"",
                  "relationship":"friends",
                  "user_avatar":"",
                  "account_type":"user",
                  "venue_details":[

                  ],
                  "brewery_details":[

                  ]
               },
               "like_id":488764809,
               "like_owner":false,
               "created_at":"Fri, 16 Mar 2018 20:35:44 +0000"
            }
         ]
      }
   ]
}
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using QuickType;
//
//    var welcome = Welcome.FromJson(jsonString);

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Welcome
    {
        [JsonProperty("toasts", NullValueHandling = NullValueHandling.Ignore)]
        public Toast[] Toasts { get; set; }
    }

    public partial class Toast
    {
        [JsonProperty("total_count", NullValueHandling = NullValueHandling.Ignore)]
        public long? TotalCount { get; set; }

        [JsonProperty("count", NullValueHandling = NullValueHandling.Ignore)]
        public long? Count { get; set; }

        [JsonProperty("auth_toast", NullValueHandling = NullValueHandling.Ignore)]
        public bool? AuthToast { get; set; }

        [JsonProperty("items", NullValueHandling = NullValueHandling.Ignore)]
        public Item[] Items { get; set; }
    }

    public partial class Item
    {
        [JsonProperty("uid", NullValueHandling = NullValueHandling.Ignore)]
        public long? Uid { get; set; }

        [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)]
        public User User { get; set; }

        [JsonProperty("like_id", NullValueHandling = NullValueHandling.Ignore)]
        public long? LikeId { get; set; }

        [JsonProperty("like_owner", NullValueHandling = NullValueHandling.Ignore)]
        public bool? LikeOwner { get; set; }

        [JsonProperty("created_at", NullValueHandling = NullValueHandling.Ignore)]
        public string CreatedAt { get; set; }
    }

    public partial class User
    {
        [JsonProperty("uid", NullValueHandling = NullValueHandling.Ignore)]
        public long? Uid { get; set; }

        [JsonProperty("user_name", NullValueHandling = NullValueHandling.Ignore)]
        public string UserName { get; set; }

        [JsonProperty("first_name", NullValueHandling = NullValueHandling.Ignore)]
        public string FirstName { get; set; }

        [JsonProperty("last_name", NullValueHandling = NullValueHandling.Ignore)]
        public string LastName { get; set; }

        [JsonProperty("bio", NullValueHandling = NullValueHandling.Ignore)]
        public string Bio { get; set; }

        [JsonProperty("location", NullValueHandling = NullValueHandling.Ignore)]
        public string Location { get; set; }

        [JsonProperty("relationship", NullValueHandling = NullValueHandling.Ignore)]
        public string Relationship { get; set; }

        [JsonProperty("user_avatar", NullValueHandling = NullValueHandling.Ignore)]
        public string UserAvatar { get; set; }

        [JsonProperty("account_type", NullValueHandling = NullValueHandling.Ignore)]
        public string AccountType { get; set; }

        [JsonProperty("venue_details", NullValueHandling = NullValueHandling.Ignore)]
        public object[] VenueDetails { get; set; }

        [JsonProperty("brewery_details", NullValueHandling = NullValueHandling.Ignore)]
        public object[] BreweryDetails { get; set; }
    }

    public partial class Welcome
    {
        public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters = { 
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}