代码之家  ›  专栏  ›  技术社区  ›  Ziggler

NewtonSoft PopulateObject-值不能为空异常

  •  1
  • Ziggler  · 技术社区  · 6 年前

    我正在尝试填充一个现有的自定义可枚举实例,该实例包含 enum 性质。当我这样做的时候,我会得到一个错误 System.ArgumentNullException: Value cannot be null JsonConvert.PopulateObject() . 什么会导致这种情况?这是我的样品:

    https://dotnetfiddle.net/CLYN3L

    我想看看是否有以下任何一种原因:

    1. 在我的班上有遗尿。

    2. 我的班级继承了 IEnumerator , IEnumerable .

    我有下面的课和我无法控制的枚举。我不能改变它们:

    public enum ErrorDisplayType : int 
    {
        PopUp = 0,
        ErrorPane = 1,
        Statusbar = 2
    }
    
    [Serializable()]
    public class ErrorObj 
    {
       private string errorCode;
       private ErrorDisplayType errorDispType;
    
       public string ErrorCode 
       {
         get { return this.errorCode; }
         set {
            this.errorCode = value;
            if (errorCode != null)
            {
               this.setFields(errorCode);
            }
         }
       }
       public ErrorDisplayType ErrorDispType 
       {
          get { return this.errorDispType; }
          set { this.errorDispType = value; }
       }
    
        private void setFields(string errorCode) 
        {
           this.errorDispType = (ErrorDisplayType)int.Parse(errorCode);
        }   
    }
    
    [Serializable]
    public class ErrorDTO : IEnumerator, IEnumerable 
    {
       private int indx = -1;
       private List<ErrorObj> errorList;
    
       public List<ErrorObj> ErrorList 
       {
         get { return this.errorList; }
         set { this.errorList = value; }
       }
    
       public ErrorDTO()
       {
            this.errorList = new List<ErrorObj>();
       }
    
       public int Add(ErrorObj error)
       {
        this.errorList.Add(error);
        return 0;  
       }
    
       public bool MoveNext()
       {
          if (indx < errorList.Count - 1)      
          {                                    
             ++indx;                          
             return true;                     
          }                                    
          else                                 
          {                                    
             indx = -1;                       
             return false;                    
          }                                    
        }
    
        public void Reset()
        {
          this.indx = -1;
        }
    
        public object Current                                                            
        {                                                                               
           get                                                                          
           {                                                                            
             if (errorList.Count == 0 || indx < 0 || indx > errorList.Count - 1)
             { 
                return null;                                                         
             }
             return this.errorList[indx];                                             
           }                                                                            
        } 
        public IEnumerator GetEnumerator()  
        {
          return (IEnumerator)this;
        }
    
    }
    

    我有一个方法(我不能更改),它给了我下面的JSON字符串

    [{
        "ErrorCode": "ABCD125",
        "ErrorDispType": 1
    }]
    

    我生成如下:

    // below is already existing code
    private static ErrorObj CreateErrorObj(string errorCode)
    {
       ErrorObj error = new ErrorObj();
       error.ErrorCode = "ABCD125";
       error.ErrorDispType = (ErrorDisplayType)int.Parse(errorCode);
       return error;    
    }
    
    public string GetErrorJSON()
    {
      ErrorDTO errDTO = new ErrorDTO();
      ErrorObj errObj = CreateErrorObj("1");
      errDTO.Add(errObj);
    
      string returnValue = Newtonsoft.Json.JsonConvert.SerializeObject(errDTO);
      return returnValue;
     }
    

    下面是我的代码,我正在尝试反序列化

    ErrorDTO errorDTO = new ErrorDTO();
    string jsonString = GetErrorJSON();
    

    下面的一行给我带来了错误。System.ArgumentNullException:值不能为空。

    Newtonsoft.Json.JsonConvert.PopulateObject(jsonString, errorDTO);
    

    请告诉我有什么问题。如果你需要更多信息,请告诉我。

    1 回复  |  直到 6 年前
        1
  •  2
  •   dbc    6 年前

    你的基本问题是你已经声明 ErrorDTO 作为 IEnumerator, IEnumerable 也就是说,一个非类型化的,非泛型的可枚举的。json.net将此类对象解释为 只读非类型化集合 ,因此当您尝试填充它时,会得到一个异常:

    System.ArgumentNullException: Value cannot be null.
       at System.RuntimeType.MakeGenericType(Type[] instantiation)
       at Newtonsoft.Json.Serialization.JsonArrayContract.CreateWrapper(Object list)
       at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Populate(JsonReader reader, Object target)
       at Newtonsoft.Json.JsonSerializer.PopulateInternal(JsonReader reader, Object target)
       at Newtonsoft.Json.JsonConvert.PopulateObject(String value, Object target, JsonSerializerSettings settings)
       at Newtonsoft.Json.JsonConvert.PopulateObject(String value, Object target)
    

    异常消息是没有用处和误导性的,但真正的原因是json.net无法知道要反序列化到的集合项的目标类型,或者对于任何非类型化的只读集合,在反序列化后添加它们的方法。

    解决这类问题的正常方法是 错误的 作为一个 ICollection<ErrorObj> 并实现必要的通用方法,从而通知json.net项类型和 Add() 方法,但不幸的是,您声明

    我不能改变他们[班级]。

    因此,最简单的解决方法是填充底层列表:

    Newtonsoft.Json.JsonConvert.PopulateObject(json, resultDTO.ErrorList);
    

    演示小提琴 here .

    推荐文章