简体   繁体   English

将JSON反序列化为IEnumerable时出错 <T> 宾语

[英]Error Deserializing JSON into IEnumerable<T> Object

The error I'm getting is as follows: 我收到的错误如下:

{"Cannot create and populate list type ReasonCodeList. Path 'AppointmentReasonList[0].ReasonCodeList', line 1, position 162."} {“无法创建和填充列表类型ReasonCodeList。路径'AppointmentReasonList [0] .ReasonCodeList',第1行,位置162。”}

I'm getting this error when converting the following sample JSON data: 转换以下样本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
                }
                                ]
        }                   
                            ]
}

I've created the following classes to try and match the data structure. 我创建了以下类来尝试匹配数据结构。

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

If, you've made it this far, I apologize for the verbose amount of code but I think all of it was necessary details. 如果到目前为止,您已经对冗长的代码感到抱歉,但是我认为所有这些都是必要的细节。

Originally I was getting the same error for this question . 本来我在这个问题上遇到同样的错误。

When I adjusted my class structure by adding the ReasonCodeList class I began getting the new error. 当我通过添加ReasonCodeList类调整类结构时,我开始遇到新错误。

The end objective is to extract every Code and Description for every reason object in the JSON and use them as parameters in an SQL Procedure. 最终目标是为JSON中的每个原因对象提取每个代码和描述,并将它们用作SQL过程中的参数。

This will require two foreach loops and the ReasonCodeList custom collection must implement IEnumerable to do so. 这将需要两个foreach循环,并且ReasonCodeList自定义集合必须实现IEnumerable才能这样做。

Any help will be greatly appreciated. 任何帮助将不胜感激。 I'm unfamiliar with the IEnumerable interface and the restrictions surrounding it. 我不熟悉IEnumerable接口及其周围的限制。

EDIT: 编辑:

In response to @Mr Hery: The following error occurs when I try to structure the AppointmentReason class as you suggested: 响应@Mr Hery:当我尝试按照您的建议构造AppointmentReason类时,发生以下错误:

{"Cannot deserialize the current JSON object (eg {\\"name\\":\\"value\\"}) into type ReasonCodeList' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly.\\r\\nTo fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\\r\\nPath 'AppointmentReasonList[0].ReasonCodeList[0].Code', line 1, position 170."} {“无法将当前JSON对象反序列化(例如{\\“ name \\”:\\“ value \\”})为ReasonCodeList类型,因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。\\ r \\ n要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化的类型,使其成为普通的.NET类型(例如,不是整数之类的原始类型,而不是一个集合) \\ r \\ nPath'AppointmentReasonList [0] .ReasonCodeList [0] .Code ',第1行,位置170。“}

I originally had this class structured with the ReasonCodeList attribute being a type of List as that's essentially what it is but got the same error. 最初,我使用“ ReasonCodeList”属性作为List的一种类型来构造该类,因为它本质上是List的类型,但存在相同的错误。 I tried replacing that with the ReasonCodeList object as was suggested in the referenced answer in the previous original post section. 我尝试按照上一原始帖子部分中引用的答案中的建议将其替换为ReasonCodeList对象。

When I made the changes, the error at the very top of this question is what occurred. 当我进行更改时,此问题最严重的错误是发生了什么。

EDIT #2 编辑#2

In response to @Frank Fajardo & his suggestion, this is what the deserialized AppointReasonResponse object will be used for: 响应@Frank Fajardo及其建议,这是反序列化的AppointReasonResponse对象将用于以下用途:

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

The attributes for the class ReasonCode due to the following error: 由于以下错误,类ReasonCode的属性:

Error 105 foreach statement cannot operate on variables of type 'AppointmentReason' because 'AppointmentReason' does not contain a public definition for 'GetEnumerator' 错误105 foreach语句无法对类型为“ AppointmentReason”的变量进行操作,因为“ AppointmentReason”不包含“ GetEnumerator”的公共定义

EDIT 3 编辑3

As @Frank Fajardo pointed out, the inner foreach loop in Edit #2 was looking at the AppointmentReason object and not its list property. 正如@Frank Fajardo指出的那样,编辑#2中的内部foreach循环正在查看AppointmentReason对象,而不是其list属性。 When the code is fixed, an error is returned much like the one I posted originally in this post. 修复代码后,将返回错误,就像我在此帖子中最初发布的一样。

New class object and modified foreach loop: 新的类对象和修改的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);
                    }
                }

Error received: 收到错误:

{"Cannot create and populate list type AppointmentReasonList. Path 'AppointmentReasonList', line 1, position 59."} {“无法创建和填充列表类型AppointmentReasonList。路径'AppointmentReasonList',第1行,位置59。”}

Maybe change your AppointmentReason to: 也许将您的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; }
    }

UPDATE 更新

Your loop ode is incorrect. 您的循环信号不正确。 It should be like this (notice the AppReason.ReasonCodeList instead of just AppReason in the inner foreach loop): 它应该像这样(注意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);
    }
}

UPDATE 2 更新2

I have no idea why you changed your AppointmentReasonResponse.AppointmentReasonList property from being of type List<AppointmentReason> to a new type AppointmentReasonList ? 我不知道您为什么将AppointmentReasonResponse.AppointmentReasonList属性从List<AppointmentReason>类型更改为新的AppointmentReasonList类型? But it appears you think you need to introduce a property which implements an enumerator. 但似乎您认为您需要引入一个实现枚举器的属性。 But you do not need it. 但是您不需要它。 A List<T> implements IEnumerable<T> . List<T>实现IEnumerable<T>

So your classes should really be just like these: 所以您的课程应该真的像这样:

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

Then you deserialise and use it as I indicated above. 然后,您按照上面的指示反序列化并使用它。

The error says that cannot create and populate list is because you have missing List<> in your code. 该错误表明cannot create and populate list是因为您的代码中缺少List<> Here's the correction: 这是更正:

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

Your JSON return an array data, so you need to put the List<> 您的JSON返回数组数据,因此您需要将List<>

Thanks everybody for all your suggestions. 感谢大家的所有建议。 I posted this question on a separate forum and received an answer the worked from Eric Lynch at codeproject.com 我在一个单独的论坛上发布了这个问题,并在codeproject.com上收到了Eric Lynch的回答。

You can view his answer here: https://www.codeproject.com/Questions/1241686/JSON-deserializer-cannot-create-populate-object 您可以在这里查看他的答案: https : //www.codeproject.com/Questions/1241686/JSON-deserializer-cannot-create-populate-object

As Eric and @Frank Fajardo point out, neither the AppointmentReasonList nor the ReasonCodeList classes need to implement IEnumerable{T} , as the List{T} type already implements the interface. 正如Eric和@Frank Fajardo指出的那样,因为List{T}类型已经实现了接口,所以AppointmentReasonListReasonCodeList类都不需要实现IEnumerable{T}

For some reason, you have to define classes that inherit from List{T} and use that class as the collection type, as opposed to just defining the property itself of a type List{T} . 由于某些原因,您必须定义从List{T}继承的类,并使用该类作为集合类型,而不是仅定义类型List{T}的属性本身。

I'm not sure why this is, because both methods seem to be doing the same thing, but when using the second method you get the following error when you try to iterate through the resulting object: 我不确定为什么会这样,因为这两种方法似乎都在做相同的事情,但是当使用第二种方法尝试遍历结果对象时,会收到以下错误:

Error 105 foreach statement cannot operate on variables of type 'AppointmentReason' because 'AppointmentReason' does not contain a public definition for 'GetEnumerator' 错误105 foreach语句无法对类型为“ AppointmentReason”的变量进行操作,因为“ AppointmentReason”不包含“ GetEnumerator”的公共定义

Not sure why this is, but at the end of the day, Eric Lynch's answer provided the desired result. 不确定为什么会这样,但是最终,埃里克·林奇(Eric Lynch)的回答提供了预期的结果。

When you have the JSON, don't hand-craft the class or guess at them, just head over to http://json2csharp.com , plug in the JSON, and let it generate the classes for you. 当您拥有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}");
    }
}

Given you original JSON, the above produced the following output. 给您原始的JSON,以上代码会产生以下输出。

Code: 851; 编码:851; Description Emergency New Patient Visit 说明紧急新病人就诊

Code: BH NEW; 代码:BH NEW; Description BH NEW 说明BH NEW

Code: 123456; 代码:123456; Description This is only a test 说明这只是一个测试

I also created a Fiddle at https://dotnetfiddle.net/170Xob . 我还在https://dotnetfiddle.net/170Xob创建了一个小提琴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM