简体   繁体   中英

Error serializing 'nested' JSON Object in C#

I'm deserializing the following JSON and having trouble with the categories/WebFilters section. I want to be able to loop through it but get the

Cannot deserialize current JSON object into type - c#´

CS1579 foreach statement cannot operate on variables of type 'WebFilters' because 'WebFilters' does not contain a public definition for 'GetEnumerator'

error when I run my code. Eventually I need to make a list of the keys and values in each of the categories as I'm using it to create a dynamic results filter - I don't know at this stage what or how many filters they'll be.

I tried changing my json, but that doesn't achieve what I want it to. I think I need to give WebFilters the ability to be iterated over...

Thanks.

{
  "Webinars": [
    {
      "date":"2017-11-08T19:21:46Z",
      "title":"Americano",
      "desc":"Nondisp fx of prox phalanx of l mid fngr, 7thG",
      "startTime":"5:39 PM",
      "endTime":"5:19 PM",
      "categories":{
        "category":"introduction",
        "timeZone":"Europe/Stockholm",
        "language":"English"
      }
    },...

Model

public class Rootobject
{
    public Webinar[] Webinars { get; set; }
    public ELearning[] ELearning { get; set; }
}

public class Webinar
{
    public DateTime Date { get; set; }
    public string Title { get; set; }
    public string Desc { get; set; }
    public string StartTime { get; set; }
    public string EndTime { get; set; }
    public WebFilters Categories { get; set; }
}

public class WebFilters
{
    public string Category { get; set; }
    public string TimeZone { get; set; }
    public string Language { get; set; }
}

View

@foreach (var webinar in Model.Webinars)
    {
       <li>@webinar.Title</li>
       <ul>
           @{ 
               var categories = webinar.Categories;
            }
            @foreach (var cat in categories)
            {
                <li>@cat</li>
            }
       </ul>
    }

Controller

public ActionResult Dashboard_Portal()
    {
        // Example JSON
        var webClient = new WebClient();
        var json = webClient.DownloadString(@"http://elliottjbrown.co.uk/portal/js/data.json");
        var webinars = JsonConvert.DeserializeObject<Rootobject>(json);
        return View(webinars);
    }

Your Categories Property in your Webinar class is not a collection of any kind, so you can't iterate over it.

You may be looking to either make it a collection:

public WebFilters Categories[] { get; set; } public WebFilters Categories[] { get; set; } or public WebFilters List<Categories> { get; set; } public WebFilters List<Categories> { get; set; }

If you actually want a collection of categories, you'll either need to have a partial view configured to render a given Category object, or you'll need to provide specific rendering inside your for loop. Something like this (note the below code will only show the one property):

@foreach (var cat in categories)
            {
                <li>@cat.Category</li>
            }

If you only expect one category for each webinar, then you'll need to refer to each property individually in the View. Here's a .NET Fiddle showing a simple render with Categories as a single object, rather than a collection Simple Display Render With Non-Collection Categories Property

<ul>
    <li>@webinar.Categories.Category</li>
    <li>@webinar.Categories.TimeZone</li>
    <li>@webinar.Categories.Language</li>
</ul>

UPDATE

Here's a link to a .NET fiddle that shows what this might look like if you're just trying to iterate through the Categories and display them: Simple Display Render With Category Collection . You'll notice that the Webinars and Elearning properties of the Rootobject are still arrays (not List<T> ), as originally defined, and the the Rootobject does not implement IEnumerable as was suggested in other answers. There's no need for those changes.

Now, if you're looking for an edit page of some kind where the user can actually select a single category from a list of options, that's a different issue and wasn't clear from your OP.

Convert the Rootobject class properties into List<> as follows:

public class Rootobject
{
    public List<Webinar> Webinars { get; set; }
}

Update 1 :

Note : Make sure Categories in the Webinar class implements the IEnumerable interface or list collection as the Json data returns an array.

Update 2 : I've updated your code and made it work using the following:

The Webinar Class :

public class Webinar
{
   public DateTime Date { get; set; }
   public string Title { get; set; }
   public string Desc { get; set; }
   public string StartTime { get; set; }
   public string EndTime { get; set; }
   public WebFilters[] Categories { get; set; } //Converted it into a collection
}

The Controller :

public ActionResult Dashboard_Portal()
{
  var webClient = new WebClient();
  var json = webClient.DownloadString(@"http://elliottjbrown.co.uk/portal/js/data.json");

  var webinars = JsonConvert.DeserializeObject<Rootobject>(json);

  return View(webinars);
}

Finally, The View :

@model DemoApp.Models.Rootobject

@{
    Layout = null;
}

<div>
    @foreach (var webinar in Model.Webinars)
    {
        <h3>@webinar.Title</h3>
        <ul>
            <li>@webinar.Categories[0].TimeZone</li>
        </ul>
    }
</div>

See the output with a screenshot:

Json对象反序列化

according to JSON-RPC spec , json is case senitive.

all of your c# class properties start with uppercases, but your json propertise with lowercases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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