【问题标题】:Error Deserializing JSON into IEnumerable<T> Object将 JSON 反序列化为 IEnumerable<T> 对象时出错
【发布时间】:2018-05-01 00:01:38
【问题描述】:

我得到的错误如下:

{"无法创建和填充列表类型 ReasonCodeList。路径 'AppointmentReasonList[0].ReasonCodeList',第 1 行,位置 162。"}

转换以下示例 JSON 数据时出现此错误:

{
    "ErrorCode":""
    ,"ErrorMessage":""
    ,"AppointmentReasonList":[
        {
            "ClassCode":"851"
            ,"ClassDescription":"newpat"
            ,"Active":true
            ,"IsPatientRelated":true
            ,"ReasonCodeList":[
                {
                    "Code":"851"
                    ,"Description":"Emergency New Patient Visit"
                    ,"Duration":15
                    ,"Active":true
                }
                ,{
                    "Code":"BH NEW"
                    ,"Description":"BH NEW"
                    ,"Duration":15
                    ,"Active":true
                }
                            ]
        }
        ,{
            "ClassCode":"ANE"
            ,"ClassDescription":"Anesthesia"
            ,"Active":true
            ,"IsPatientRelated":true
            ,"ReasonCodeList":[
                {
                    "Code":"123456"
                    ,"Description":"This is only a test"
                    ,"Duration":15
                    ,"Active":true
                }
                                ]
        }                   
                            ]
}

我创建了以下类来尝试匹配数据结构。

public class AppointmentReasonResponse
        {
            public string ErrorCode { get; set; }
            public string ErrorMessage { get; set; }
            public List<AppointmentReason> AppointmentReasonList { get; set; }
        }

        public class AppointmentReason
        {
            public string ClassCode { get; set; }
            public string ClassDescription { get; set; }
            public bool Active { get; set; }
            public bool IsPatientRelated { get; set; }
            public ReasonCodeList ReasonCodeList { get; set; }
        }

        public class ReasonCodeList:IEnumerable<ReasonCode>
        {
            public List<ReasonCode> ReasonCodeLi { get; set; }

            IEnumerator<ReasonCode> IEnumerable<ReasonCode>.GetEnumerator()
            {
                // Return the array object's IEnumerator.
                foreach (ReasonCode Reason in ReasonCodeLi)
                {
                    yield return Reason;
                }
            }

            public IEnumerator<ReasonCode> GetEnumerator()
            {
                // Return the array object's IEnumerator.
                return ReasonCodeLi.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                // call the generic version of the method
                return this.GetEnumerator();
            }
        }

        public class ReasonCode
        {
            public string Code { get; set; }
            public string Description { get; set; }
            public int Duration { get; set; }
            public bool Active { get; set; }
        }

如果你已经做到了这一步,我为冗长的代码道歉,但我认为所有这些都是必要的细节。

最初我遇到了同样的错误question

当我通过添加 ReasonCodeList 类来调整我的类结构时,我开始收到新错误。

最终目标是提取 JSON 中每个原因对象的每个代码和描述,并将它们用作 SQL 过程中的参数。

这将需要两个 foreach 循环,并且 ReasonCodeList 自定义集合必须实现 IEnumerable 才能这样做。

任何帮助将不胜感激。我不熟悉 IEnumerable 接口及其周围的限制。

编辑:

回复@Mr Hery:当我尝试按照您的建议构建 AppointmentReason 类时出现以下错误:

{"无法反序列化当前的 JSON 对象(例如 {\"name\":\"value\"}) 输入类型 ReasonCodeList' 因为类型需要 正确反序列化的 JSON 数组(例如 [1,2,3])。\r\n修复此问题 错误将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改 反序列化的类型,使其成为普通的 .NET 类型(例如,不是 像整数这样的原始类型,而不是像数组这样的集合类型或 List) 可以从 JSON 对象反序列化。 JsonObjectAttribute 也可以添加到类型中以强制它 从 JSON 对象反序列化。\r\n路径 'AppointmentReasonList[0].ReasonCodeList[0].Code',第 1 行,位置 170."}

我最初使用 ReasonCodeList 属性作为 List 类型构造了这个类,因为它本质上就是这样,但得到了同样的错误。我尝试用上一个原始帖子部分中引用的答案中建议的 ReasonCodeList 对象替换它。

当我进行更改时,这个问题最顶部的错误就是发生了什么。

编辑#2

响应@Frank Fajardo 和他的建议,这就是反序列化的 ApppointReasonResponse 对象的用途:

    jarray = JsonConvert.DeserializeObject<AppointmentReasonResponse>(json);
    foreach (AppointmentReason ApptReason in jarray.AppointmentReasonList)
    {
        foreach (ReasonCode Reason in ApptReason)
        {
            AddInterfacePMReasonCode(PracticeID, Reason.Code, Reason.Description);
        }
    }

原因代码类的属性由于以下错误:

错误 105 foreach 语句不能对类型变量进行操作 'AppointmentReason' 因为 'AppointmentReason' 不包含 'GetEnumerator' 的公共定义

编辑 3

正如@Frank Fajardo 所指出的,Edit #2 中的内部 foreach 循环查看的是 AppointmentReason 对象,而不是它的 list 属性。修复代码后,返回的错误很像我最初在这篇文章中发布的错误。

新的类对象和修改的foreach循环:

public class AppointmentReasonResponse
        {
            public string ErrorCode { get; set; }
            public string ErrorMessage { get; set; }
            public AppointmentReasonList AppointmentReasonList { get; set; }
        }

        public class AppointmentReasonList : IEnumerable<AppointmentReason>
        {

            public List<AppointmentReason> AppointmentReasonLi { get; set; }

            IEnumerator<AppointmentReason> IEnumerable<AppointmentReason>.GetEnumerator()
            {
                foreach (AppointmentReason ApptReason in AppointmentReasonLi)
                {
                    yield return ApptReason;
                }
            }

            public IEnumerator<AppointmentReason> GetEnumerator()
            {
                return AppointmentReasonLi.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
        }

foreach (AppointmentReason ApptReason in jarray.AppointmentReasonList)
                {
                    foreach (ReasonCode Reason in ApptReason.ReasonCodeList)
                    {
                        AddInterfacePMReasonCode(PracticeID, Reason.Code, Reason.Description);
                    }
                }

收到错误:

{"无法创建和填充列表类型 AppointmentReasonList.Path 'AppointmentReasonList',第 1 行,位置 59。"}

【问题讨论】:

  • 请把反序列化的代码也放上去。
  • public ReasonCodeList ReasonCodeList { get; set; } 必须是 public List&lt;ReasonCodeList&gt; ReasonCodeList { get; set; }
  • 您是否已清除构建然后重新构建?如果错误仍然出现,也许可以尝试修改ReasonCodeList类的枚举。
  • 另外不要忘记检查来自ReasonCodeList 的数据。它们必须与 JSON 数据相等。
  • @Mr Hery 我按照您的建议清理并重建了项目,并且遇到了同样的错误。此外,我使用我提供的示例 JSON 响应仔细检查了 ReasonCodeResponse 以及其他类对象。我没有看到任何不一致的地方

标签: c# json.net deserialization ienumerable


【解决方案1】:

也许把你的AppointmentReason改成:

    public class AppointmentReason
    {
        public string ClassCode { get; set; }
        public string ClassDescription { get; set; }
        public bool Active { get; set; }
        public bool IsPatientRelated { get; set; }
        public List<ReasonCode> ReasonCodeList { get; set; }
    }

更新

您的循环颂歌不正确。应该是这样的(注意AppReason.ReasonCodeList 而不是内部foreach 循环中的AppReason):

jarray = JsonConvert.DeserializeObject<AppointmentReasonResponse>(json);
foreach (AppointmentReason ApptReason in jarray.AppointmentReasonList)
{
    foreach (ReasonCode Reason in ApptReason.ReasonCodeList)
    {
        AddInterfacePMReasonCode(PracticeID, Reason.Code, Reason.Description);
    }
}

更新 2

我不知道您为什么将 AppointmentReasonResponse.AppointmentReasonList 属性从 List&lt;AppointmentReason&gt; 类型更改为新类型 AppointmentReasonList?但是您似乎认为您需要引入一个实现枚举器的属性。但你不需要它。 A List&lt;T&gt; implements IEnumerable&lt;T&gt;.

所以你的课程应该是这样的:

    public class AppointmentReasonResponse
    {
        public string ErrorCode { get; set; }
        public string ErrorMessage { get; set; }
        public List<AppointmentReason> AppointmentReasonList { get; set; }
    }

    public class AppointmentReason
    {
        public string ClassCode { get; set; }
        public string ClassDescription { get; set; }
        public bool Active { get; set; }
        public bool IsPatientRelated { get; set; }
        public List<ReasonCode> ReasonCodeList { get; set; }
    }

    public class ReasonCode
    {
        public string Code { get; set; }
        public string Description { get; set; }
        public int Duration { get; set; }
        public bool Active { get; set; }
    }

然后你反序列化并按照我上面的指示使用它。

【讨论】:

  • 感谢您的回复。请参阅问题中所做的编辑,参考 Hery 先生的回答,了解您提出建议时发生的错误。
  • 你试过我的建议了吗? (看起来你没有。)
  • 你说得对,弗兰克。我以为你提出的建议和赫里先生的建议一样,但我错了。即使这将正确地反序列化为 AppointmentReasonResponse,新对象也将无法执行其要循环的最终任务并将其属性作为参数添加到 SQL 连接。我将在答案中发布相关代码和错误作为编辑
  • @W.Harr,您的内部foreach 循环正在查看一个对象(AppointmentReason 类型)而不是该对象中的列表属性(即名为ReasonCodeList 的属性),所以它抱怨该对象不是可枚举/集合。请参阅我的更新,了解您应该如何做。
  • 您指出内部 foreach 循环没有查看对象中的 list 属性是正确的。我按照您的建议更新了我的代码,但我开始收到与我在问题开始时发布的相同类型的错误,即程序无法创建和填充对象。我将在帖子中发布确切的错误。
【解决方案2】:

感谢大家的所有建议。我在一个单独的论坛上发布了这个问题,并收到了来自 codeproject.com 的 Eric Lynch 的回答

你可以在这里查看他的回答:https://www.codeproject.com/Questions/1241686/JSON-deserializer-cannot-create-populate-object

正如 Eric 和 @Frank Fajardo 所指出的,AppointmentReasonListReasonCodeList 类都不需要实现 IEnumerable{T},因为 List{T} 类型已经实现了接口。

出于某种原因,您必须定义继承自 List{T} 的类并将该类用作集合类型,而不是仅定义类型 List{T} 的属性本身。

我不确定这是为什么,因为这两种方法似乎都在做同样的事情,但是当使用第二种方法时,当您尝试遍历生成的对象时会出现以下错误:

错误 105 foreach 语句不能对类型变量进行操作 'AppointmentReason' 因为 'AppointmentReason' 不包含 'GetEnumerator' 的公共定义

不知道为什么会这样,但归根结底,Eric Lynch 的回答提供了预期的结果。

【讨论】:

    【解决方案3】:

    错误表明cannot create and populate list 是因为您的代码中缺少List&lt;&gt;。以下是更正:

    public class AppointmentReasonResponse
    {
        public string ErrorCode { get; set; }
        public string ErrorMessage { get; set; }
        public List<AppointmentReason> AppointmentReasonList { get; set; }
    }
    
    public class AppointmentReason
    {
        public string ClassCode { get; set; }
        public string ClassDescription { get; set; }
        public bool Active { get; set; }
        public bool IsPatientRelated { get; set; }
        public List<ReasonCodeList> ReasonCodeList { get; set; }
    }
    
    public class ReasonCodeList:IEnumerable<ReasonCode>
    {
        public List<ReasonCode> ReasonCodeLi { get; set; }
    
        IEnumerator<ReasonCode> IEnumerable<ReasonCode>.GetEnumerator()
        {
            // Return the array object's IEnumerator.
            foreach (ReasonCode Reason in ReasonCodeLi)
            {
                yield return Reason;
            }
        }
    
        public IEnumerator<ReasonCode> GetEnumerator()
        {
            // Return the array object's IEnumerator.
            return ReasonCodeLi.GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            // call the generic version of the method
            return this.GetEnumerator();
        }
    }
    
    public class ReasonCode
    {
        public string Code { get; set; }
        public string Description { get; set; }
        public int Duration { get; set; }
        public bool Active { get; set; }
    }
    

    你的JSON返回一个数组数据,所以你需要把List&lt;&gt;

    【讨论】:

      【解决方案4】:

      当您拥有 JSON 后,不要手工制作类或猜测它们,只需前往 http://json2csharp.com,插入 JSON,让它为您生成类。

      public class ReasonCodeList
      {
          public string Code { get; set; }
          public string Description { get; set; }
          public int Duration { get; set; }
          public bool Active { get; set; }
      }
      
      public class AppointmentReasonList
      {
          public string ClassCode { get; set; }
          public string ClassDescription { get; set; }
          public bool Active { get; set; }
          public bool IsPatientRelated { get; set; }
          public List<ReasonCodeList> ReasonCodeList { get; set; }
      }
      
      public class RootObject
      {
          public string ErrorCode { get; set; }
          public string ErrorMessage { get; set; }
          public List<AppointmentReasonList> AppointmentReasonList { get; set; }
      }
      
      var root = JsonConvert.DeserializeObject<RootObject>(json);
      
      foreach (var appointmentReason in root.AppointmentReasonList)
      {
          foreach (var reasonCode in appointmentReason.ReasonCodeList)
          {
              Console.WriteLine($"Code: {reasonCode.Code}; Description {reasonCode.Description}");
          }
      }
      

      给定原始 JSON,上面产生了以下输出。

      代码:851;描述紧急新患者就诊

      代码:BH NEW;说明 BH 新

      代码:123456;说明 这只是一个测试

      我还在 https://dotnetfiddle.net/170Xob 创建了一个 Fiddle。

      【讨论】:

      • 我最初确实使用了那个确切的链接。它的问题是它没有为它创建的任何类使用 IEnumerable 接口,所以我不能以我需要的方式循环对象。
      • 您的声明没有意义,因为您的原始帖子说“最终目标是为每个原因对象提取每个代码和描述......”检查上面的更新。
      猜你喜欢
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      相关资源
      最近更新 更多