0

I am trying to deserialize a JSON string from a REST Api response and then show it on a ListView in Xamarin.forms. This is what I got so far:

-TheMainPage.xaml.cs where I connect to the api and (should) deserialize the response.

-The MainPage.xaml where I created the ListView for display.

-The UserModel.cs where I stored the model for the JSON I am receiving from the API (Pasted the JSON here: https://app.quicktype.io/ to get the class).

MainPage.xaml.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using RESTListView;


namespace RESTListViewApp
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            GETRequest();
        }

        private async void GETRequest()
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "dXNlcjQyMzIxNTQwMzMwMjI0OmE2YTZjZDMyLWQ4NTItNGZlNS04NmMxLWE3NTFhMWUyNmZlNA==");

            string url = "https://shared-sandbox-api.marqeta.com/v3/users";

            var result = await client.GetAsync(url);
            var json = result.Content.ReadAsStringAsync().Result;

            Users model = Users.FromJson(json);

            MyListView.ItemsSource = model;
        }

    }
}

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:RESTListViewApp"
             x:Class="RESTListViewApp.MainPage">


    <StackLayout>
        <StackLayout HorizontalOptions="Center">
            <Button Text="ADD"/>
            <Button Text="DELETE"/>
        </StackLayout>
        <ListView x:Name="MyListView" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout HorizontalOptions="Center">
                            <Label Text="{Binding Token}"/>
                            <Label Text="{Binding FirstName}"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

    </StackLayout>

</ContentPage>

UserModel.cs

    // <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using RESTListView;
//
//    var users = Users.FromJson(jsonString);

namespace RESTListView
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Users
    {
        [JsonProperty("count")]
        public long Count { get; set; }

        [JsonProperty("start_index")]
        public long StartIndex { get; set; }

        [JsonProperty("end_index")]
        public long EndIndex { get; set; }

        [JsonProperty("is_more")]
        public bool IsMore { get; set; }

        [JsonProperty("data")]
        public Datum[] Data { get; set; }
    }

    public partial class Datum
    {
        [JsonProperty("token")]
        public string Token { get; set; }

        [JsonProperty("active")]
        public bool Active { get; set; }

        [JsonProperty("first_name", NullValueHandling = NullValueHandling.Ignore)]
        public string FirstName { get; set; }

        [JsonProperty("email")]
        public string Email { get; set; }

        [JsonProperty("phone", NullValueHandling = NullValueHandling.Ignore)]
        public string Phone { get; set; }

        [JsonProperty("parent_token", NullValueHandling = NullValueHandling.Ignore)]
        public Guid? ParentToken { get; set; }

        [JsonProperty("uses_parent_account")]
        public bool UsesParentAccount { get; set; }

        [JsonProperty("corporate_card_holder")]
        public bool CorporateCardHolder { get; set; }

        [JsonProperty("company", NullValueHandling = NullValueHandling.Ignore)]
        public string Company { get; set; }

        [JsonProperty("created_time")]
        public DateTimeOffset CreatedTime { get; set; }

        [JsonProperty("last_modified_time")]
        public DateTimeOffset LastModifiedTime { get; set; }

        [JsonProperty("business_token", NullValueHandling = NullValueHandling.Ignore)]
        public Guid? BusinessToken { get; set; }

        [JsonProperty("metadata")]
        public Metadata Metadata { get; set; }

        [JsonProperty("account_holder_group_token")]
        public string AccountHolderGroupToken { get; set; }

        [JsonProperty("status")]
        public string Status { get; set; }
    }

    public partial class Metadata
    {
    }

    public partial class Users
    {
        public static Users FromJson(string json) => JsonConvert.DeserializeObject<Users>(json, RESTListView.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Users self) => JsonConvert.SerializeObject(self, RESTListView.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

Example JSON to deserialize

{
  "count" : 5,
  "start_index" : 0,
  "end_index" : 4,
  "is_more" : true,
  "data" : [ {
    "token" : "9dd1c8bd-9de8-4c36-8f33-d088f843b053",
    "active" : true,
    "first_name" : "Dhd Fh",
    "email" : "TEMPORARY_5cab6e5f-8d8c-44f2-aa4a-ad3d1caed890_ffg@ff.gg",
    "phone" : "+375291766633",
    "parent_token" : "1074bcd0-8e92-4158-8edf-71b6039c7059",
    "uses_parent_account" : true,
    "corporate_card_holder" : false,
    "company" : " fggg",
    "created_time" : "2018-11-19T07:11:33Z",
    "last_modified_time" : "2018-11-19T07:11:33Z",
    "business_token" : "1074bcd0-8e92-4158-8edf-71b6039c7059",
    "metadata" : { },
    "account_holder_group_token" : "DEFAULT_AHG",
    "status" : "ACTIVE"
  }, {
    "token" : "c26623b3-e1ac-47d5-82b5-890771cb5450",
    "active" : true,
    "first_name" : "Dhd Fh",
    "email" : "TEMPORARY_2f34b134-1b76-4a69-a4c3-945d971cf70a_fud@dhd.dhd",
    "phone" : "+375291766633",
    "parent_token" : "85b279c6-4c3a-45cd-8a8c-c7c361f5b413",
    "uses_parent_account" : true,
    "corporate_card_holder" : false,
    "company" : "fjf",
    "created_time" : "2018-11-19T07:07:33Z",
    "last_modified_time" : "2018-11-19T07:07:33Z",
    "business_token" : "85b279c6-4c3a-45cd-8a8c-c7c361f5b413",
    "metadata" : { },
    "account_holder_group_token" : "DEFAULT_AHG",
    "status" : "ACTIVE"
  }, {
    "token" : "B$_C_zlq3yedu",
    "active" : true,
    "email" : "B$_C_zlq3yedu@square.invalid",
    "uses_parent_account" : false,
    "corporate_card_holder" : false,
    "created_time" : "2018-11-19T05:16:52Z",
    "last_modified_time" : "2018-11-19T05:16:52Z",
    "metadata" : { },
    "account_holder_group_token" : "DEFAULT_AHG",
    "status" : "ACTIVE"
  }, {
    "token" : "B$_C_svutldl3",
    "active" : true,
    "email" : "B$_C_svutldl3@square.invalid",
    "uses_parent_account" : false,
    "corporate_card_holder" : false,
    "created_time" : "2018-11-19T04:50:18Z",
    "last_modified_time" : "2018-11-19T04:50:18Z",
    "metadata" : { },
    "account_holder_group_token" : "DEFAULT_AHG",
    "status" : "ACTIVE"
  }, {
    "token" : "B$_C_4wzzylny",
    "active" : true,
    "email" : "B$_C_4wzzylny@square.invalid",
    "uses_parent_account" : false,
    "corporate_card_holder" : false,
    "created_time" : "2018-11-19T04:11:13Z",
    "last_modified_time" : "2018-11-19T04:11:13Z",
    "metadata" : { },
    "account_holder_group_token" : "DEFAULT_AHG",
    "status" : "ACTIVE"
  } ]
}

But when I run the program I get this error: Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'RESTListView.Users[]' 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<T>) that can be deserialized from a JSON object.

https://i.stack.imgur.com/dtxr5.png [Exception Image]

Any help on how to achieve this would be appreciated.

Juxen
  • 3
  • 4
  • plz try https://stackoverflow.com/questions/18192357/deserializing-json-object-array-with-json-net – Daniel B Nov 19 '18 at 02:35
  • the error message is self-explanatory - did you actually read it? Your JSON is a single object, not an array, and you are trying to deserialize it into an array type. Either correct the JSON to be an array, or correct your deserialization to use a single object type. – Jason Nov 19 '18 at 02:47
  • Thanks for the clarification Jason, that solves the problem for the JSON deserialization but now I am not able to pass the values of the deserialized JSON to the ItemSource property of my ListView so I can see the data. Could you please tell me how to display the converted JSON using the ListView I created or any other method? Thanks for your support. – Juxen Nov 19 '18 at 03:13
  • "I am not able to pass the values of the deserialized JSON to the ItemSource" - what does this mean? Are you getting an error or exception? Are you sure that your data is actually getting deserialized correctly and that the model contains data? – Jason Nov 19 '18 at 03:19
  • I am getting a type conversion error since the ItemSource property of the ListView is of type 'System.Collections.IEnumerable and the model that Im passing is of type Users. You can see it at the bottom of my MainPage.xaml.cs. I need to pass the data inside the model to the ItemSource so the converted JSON can be displayed on my ListView. If you know any other way on how I can display the deserialized JSON stored in 'model' I would really appreciate it. – Juxen Nov 19 '18 at 03:45

2 Answers2

1

your ItemsSource must be an IEnumerable (ie, a collection or list).

Users model = Users.FromJson(json);

List<Users> users = new List<Users>();
users.Add(model);

MyListView.ItemsSource = users;
Jason
  • 86,222
  • 15
  • 131
  • 146
0

Try listview binding like :

Users model = Users.FromJson(json);

MyListView.ItemsSource = model.Data;

And Replace your partial class like:

 public partial class Users
{
    [JsonProperty("count")]
    public long Count { get; set; }

    [JsonProperty("start_index")]
    public long StartIndex { get; set; }

    [JsonProperty("end_index")]
    public long EndIndex { get; set; }

    [JsonProperty("is_more")]
    public bool IsMore { get; set; }

    [JsonProperty("data")]
    public List<Datum> Data { get; set; }
}
Srusti Thakkar
  • 1,835
  • 2
  • 22
  • 52