title: Xamarin grouped ListView: How to convert JSON into a model made for grouped ListView
body: <p>I'm loading categories from an ASP.NET Core backend as an array into a Xamarin app for a ListView with grouped items like here <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/customizing-list-appearance#grouping" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/customizing-list-appearance#grouping</a>.</p>
  <pre><code>09-06 23:25:36.679 W/SSLCertificateSocketFactory(29717): Bypassing SSL security checks at caller's request
  [0:] Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {&quot;name&quot;:&quot;value&quot;}) into type 'BoerPlaza.Models.Products.Category' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
  To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List&lt;T&gt;) 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.
  Path '[0].id', line 1, position 7.
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x003a0] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList (System.Collections.IList list, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, System.String id) [0x00173] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue, System.String id) [0x000dc] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0007f] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000db] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00054] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in &lt;2073514815234917a5e8f91b0b239405&gt;:0 
    at BoerPlaza.Services.CategoryDataStore.GetCategoriesParentAsync () [0x0013b] in C:\Users\QuanDar\source\repos\BoerPlaza\Frontend\BoerPlaza\BoerPlaza\Services\CategoryDataStore.cs:47 
    at BoerPlaza.ViewModels.BrowseCategoryViewModel.ExecuteLoadCategoriesCommand () [0x00068] in C:\Users\QuanDar\source\repos\BoerPlaza\Frontend\BoerPlaza\BoerPlaza\ViewModels\BrowseCategoryViewModel.cs:49 
  </code></pre>
  <p>The problem with the model is that you have to inherit from ObservableCollection. All the other models are working fine, it's just this one I can't make work because of the inheritance. When I remove the inheritance, everything works great, but I can't group my items in the ListView then.</p>
  <p>Tried List instead of ObservableCollection. Does not matter.
  Xamarin Model: (EF Core model not included, but JSON should show what is available)</p>
  <pre><code>    public class Category : ObservableCollection&lt;Category&gt;
      {
          public int Id { get; set; }
          public string Title { get; set; }
          public string Description { get; set; }
          public Category Parent { get; set; }
          public Image Image { get; set; }
          public ObservableCollection&lt;Category&gt; Children =&gt; this;
  
          public Category(string title)
          {
              this.Title = title;
          }
  
          public Category()
          {
  
          }
       }
  </code></pre>
  <p>JSON from backend:</p>
  <pre><code>  [
        {
        &quot;id&quot;: 1,
        &quot;title&quot;: &quot;Vlees&quot;,
        &quot;description&quot;: null,
        &quot;parent&quot;: null,
        &quot;image&quot;: {
          &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
          &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
        },
        &quot;children&quot;: [
          {
          &quot;id&quot;: 5,
          &quot;title&quot;: &quot; Kip&quot;,
           &quot;description&quot;: null,
           &quot;image&quot;: {
             &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
             &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
            },
            &quot;children&quot;: []
            },
            {
           &quot;id&quot;: 6,
           &quot;title&quot;: &quot;Koe&quot;,
           &quot;description&quot;: null,
           &quot;image&quot;: {
             &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
             &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
           },
          &quot;children&quot;: []
         }
        ]
        },
        {
        &quot;id&quot;: 2,
      &quot;title&quot;: &quot;Groente&quot;,
      &quot;description&quot;: null,
      &quot;parent&quot;: null,
      &quot;image&quot;: {
        &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
        &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: [
        {
        &quot;id&quot;: 9,
        &quot;title&quot;: &quot;Boemkool&quot;,
        &quot;description&quot;: null,
        &quot;image&quot;: {
        &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
        &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
        },
        &quot;children&quot;: []
      }
      ]
      },
      {
      &quot;id&quot;: 3,
      &quot;title&quot;: &quot;Fruit&quot;,
      &quot;description&quot;: null,
      &quot;parent&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: [
      {
      &quot;id&quot;: 10,
      &quot;title&quot;: &quot;Appel&quot;,
      &quot;description&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: []
      },
      {
      &quot;id&quot;: 11,
      &quot;title&quot;: &quot;Peer&quot;,
      &quot;description&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: []
      }
      ]
      },
      {
      &quot;id&quot;: 4,
      &quot;title&quot;: &quot;Kruiden&quot;,
      &quot;description&quot;: null,
      &quot;parent&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: [
      {
      &quot;id&quot;: 12,
      &quot;title&quot;: &quot;Knoflook&quot;,
      &quot;description&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: []
      },
      {
      &quot;id&quot;: 13,
      &quot;title&quot;: &quot;Peterselie&quot;,
      &quot;description&quot;: null,
      &quot;image&quot;: {
      &quot;alt&quot;: &quot;Bedrijven WordPress themes&quot;,
      &quot;pathThumbnail&quot;: &quot;Templates/constructie.jpg&quot;
      },
      &quot;children&quot;: []
      }
      ]
      }
      ]
  </code></pre>
  <p>HTTP Service</p>
  <pre><code>public async Task&lt;IEnumerable&lt;Category&gt;&gt; GetCategoriesParentAsync()
  {
      if (IsConnected)
      {
          var json = await client.GetStringAsync($&quot;api/products/categories/parent&quot;);
          return await Task.Run(() =&gt; JsonConvert.DeserializeObject&lt;IEnumerable&lt;Category&gt;&gt;(json));
      }
  
      return this.categories;
  
  }
  </code></pre>
  <p>ViewModel:
  When I set the array myself, everything works fine.</p>
  <pre><code>    public ObservableCollection&lt;Category&gt; Categories { get; set; }
  ...
      public async Task ExecuteLoadCategoriesCommand()
      {
          IsBusy = true;
      this.PreviousCategoryHolder.Add(this.Categories);
  
      try
      {
         
          Categories.Clear();
          // This does not work and throws the error
          //var categories  = await CategoryStore.GetCategoriesParentAsync();
          //foreach (var category in categories)
          //{
          //    Categories.Add(category);
          //}
         
          // when I do it like this, it works and displays the items.
          this.Categories = new ObservableCollection&lt;Category&gt; 
          {
              new Category(&quot;Vlees&quot;)
              {
                  new Category(&quot;kip&quot;),
                  new Category(&quot;kip file&quot;)
  
              },
              new Category(&quot;Groente&quot;)
              {
                  new Category(&quot;Appel&quot;),
                  new Category(&quot;Banaan&quot;)
              }
          };
      }
      catch (Exception ex)
      {
          Debug.WriteLine(ex);
      }
      finally
      {
          IsBusy = false;
      }
  }
  </code></pre>
  <p>xaml:</p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
  &lt;ContentPage  
               xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
               xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot; 
               x:Class=&quot;BoerPlaza.Views.BrowsePage&quot;&gt;
      &lt;!-- binding context is in code behind --&gt;
      &lt;ContentPage.Content&gt;
          &lt;ListView x:Name =&quot;categoriesListView&quot; 
                    IsGroupingEnabled=&quot;true&quot; 
                    ItemTapped=&quot;Handle_ItemTapped&quot;
                    CachingStrategy=&quot;RecycleElement&quot;
                    &gt;
              &lt;ListView.GroupHeaderTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;TextCell Text=&quot;{Binding Title}&quot;/&gt;
                  &lt;/DataTemplate&gt;
              &lt;/ListView.GroupHeaderTemplate&gt;
              &lt;ListView.ItemTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;TextCell Text=&quot;{Binding Title}&quot;/&gt;
                  &lt;/DataTemplate&gt;
              &lt;/ListView.ItemTemplate&gt;
          &lt;/ListView&gt;
      &lt;/ContentPage.Content&gt;
  &lt;/ContentPage&gt;
  </code></pre>
  <p>Thanks!</p>