Unable to parse json data into a List of dictionary

Hi Experts,

I am unable to parse the JSON DATA in C#

the data is

"{\"data\":

{\"6\":{\"id\":\"6\",\"reward_definition_id\":12,\"person_id\":164305,\"issue_date\":\"2015-10-08\",\"expiry_date\":\"2015-11-08\",\"amount_initial\":20,\"amount_remaining\":0,\"

_member_details\":{\"id\":\"164305\",\"first_name\":\"test\",\"last_name\":\"one\",\"email\":\"testing1@example.com\",\"_email_trigger\":\"Y\",\"_email_bounced\":\"N\",\"_email_promo\":\"Y\",\"_app_notify\":\"Y\",\"_sms_status\":\"Y\",\"active\":\"Y\"},

\"_store_details\":null,\"_staff_details\":null,\"_product_details\":null},

\"5\":{\"id\":\"5\",\"reward_definition_id\":12,\"person_id\":164305,\"issue_date\":\"2015-10-08\",\"expiry_date\":\"2015-11-08\",\"amount_initial\":20,\"amount_remaining\":20,\"

_member_details\":{\"id\":\"164305\",\"first_name\":\"test\",\"last_name\":\"one\",\"email\":\"testing1@example.com\",\"_email_trigger\":\"Y\",\"_email_bounced\":\"N\",\"_email_promo\":\"Y\",\"_app_notify\":\"Y\",\"_sms_status\":\"Y\",\"active\":\"Y\"},

\"_store_details\":null,\"_staff_details\":null,\"_product_details\":null}

}}"

Open in new window


How to create a Class with Dictionary of lists of this data and deserialize it into C# class.

The class I am trying to parse and store this in the following classes.

public class JsonRewardResponse
{
    public Dictionary<int, JsonRewardDetails> mydictionary { get; set; }
}

public class JsonRewardDetails
{
	public string Id;
	public int reward_definition_id;
	public int person_id;
	public string issue_date;
	public string expiry_date;
	public int amount_initial;
	public int amount_remaining;
    public JsonMemberDetails member;
	public int _store_details;
	public int _staff_details;
	public int product_details;
}
public class JsonMemberDetails
{
    public string Id;
    public string first_name;
    public string last_name;
    public string email;
    public string _email_trigger;
    public string _email_bounced;
    public string _email_promo;
    public string _app_notify;
    public string _sms_status;
    public string active;
}

Open in new window


Please help,

Thanks in Advance.

Bharath AK
LVL 1
Bharath A.KAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

it_saigeDeveloperCommented:
I would imagine it's because your data structure is off.

I get the following:
{"data":{"6":{"Id":"6","reward_definition_id":12,"person_id":164305,"issue_date":"2015-10-08","expiry_date":"2015-11-08","amount_initial":20,"amount_remaining":0,"member_details":{"Id":"164305","first_name":"test","last_name":"one","email":"testing1@example.com","_email_trigger":"Y","_email_bounced":"N","_email_promo":"Y","_app_notify":"Y","_sms_status":"Y","active":"Y"},"_store_details":null,"_staff_details":null,"product_details":null},"5":{"Id":"5","reward_definition_id":12,"person_id":164305,"issue_date":"2015-10-08","expiry_date":"2015-11-08","amount_initial":20,"amount_remaining":20,"member_details":{"Id":"164305","first_name":"test","last_name":"one","email":"testing1@example.com","_email_trigger":"Y","_email_bounced":"N","_email_promo":"Y","_app_notify":"Y","_sms_status":"Y","active":"Y"},"_store_details":null,"_staff_details":null,"product_details":null}}}

Open in new window

When using the following class layout:
public class JsonRewardResponse
{
	public Dictionary<int, JsonRewardDetails> data { get; set; }
}

public class JsonRewardDetails
{
	public string Id { get; set; }
	public int reward_definition_id { get; set; }
	public int person_id { get; set; }
	public string issue_date { get; set; }
	public string expiry_date { get; set; }
	public int amount_initial { get; set; }
	public int amount_remaining { get; set; }
	public JsonMemberDetails member_details { get; set; }
	public int? _store_details { get; set; }
	public int? _staff_details { get; set; }
	public int? product_details { get; set; }
}

public class JsonMemberDetails
{
	public string Id { get; set; }
	public string first_name { get; set; }
	public string last_name { get; set; }
	public string email { get; set; }
	public string _email_trigger { get; set; }
	public string _email_bounced { get; set; }
	public string _email_promo { get; set; }
	public string _app_notify { get; set; }
	public string _sms_status { get; set; }
	public string active { get; set; }
}

Open in new window

Feeding the produced Json into http://json.parser.online.fr/ produces the following results:Capture.JPGFrom this I can deserialize the data using the Newtonsoft libraries; e.g. -
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace EE_Q28829779
{
	class Program
	{
		static readonly string json = @"{ ""data"":{ ""6"":{ ""Id"":""6"", ""reward_definition_id"":12, ""person_id"":164305, ""issue_date"":""2015-10-08"", ""expiry_date"":""2015-11-08"", ""amount_initial"":20, ""amount_remaining"":0, ""member_details"":{ ""Id"":""164305"", ""first_name"":""test"", ""last_name"":""one"", ""email"":""testing1@example.com"", ""_email_trigger"":""Y"", ""_email_bounced"":""N"", ""_email_promo"":""Y"", ""_app_notify"":""Y"", ""_sms_status"":""Y"", ""active"":""Y"" }, ""_store_details"":null, ""_staff_details"":null, ""product_details"":null }, ""5"":{ ""Id"":""5"", ""reward_definition_id"":12, ""person_id"":164305, ""issue_date"":""2015-10-08"", ""expiry_date"":""2015-11-08"", ""amount_initial"":20, ""amount_remaining"":20, ""member_details"":{ ""Id"":""164305"", ""first_name"":""test"", ""last_name"":""one"", ""email"":""testing1@example.com"", ""_email_trigger"":""Y"", ""_email_bounced"":""N"", ""_email_promo"":""Y"", ""_app_notify"":""Y"", ""_sms_status"":""Y"", ""active"":""Y"" }, ""_store_details"":null, ""_staff_details"":null, ""product_details"":null } } }";

		static void Main(string[] args)
		{
			JsonRewardResponse response = JsonConvert.DeserializeObject<JsonRewardResponse>(json);
			foreach (var detail in response.data)
				Console.WriteLine(detail.Value.Id);
			Console.ReadLine();
		}
	}

	public class JsonRewardResponse
	{
		public Dictionary<int, JsonRewardDetails> data { get; set; }
	}

	public class JsonRewardDetails
	{
		public string Id { get; set; }
		public int reward_definition_id { get; set; }
		public int person_id { get; set; }
		public string issue_date { get; set; }
		public string expiry_date { get; set; }
		public int amount_initial { get; set; }
		public int amount_remaining { get; set; }
		public JsonMemberDetails member_details { get; set; }
		public int? _store_details { get; set; }
		public int? _staff_details { get; set; }
		public int? product_details { get; set; }
	}
	public class JsonMemberDetails
	{
		public string Id { get; set; }
		public string first_name { get; set; }
		public string last_name { get; set; }
		public string email { get; set; }
		public string _email_trigger { get; set; }
		public string _email_bounced { get; set; }
		public string _email_promo { get; set; }
		public string _app_notify { get; set; }
		public string _sms_status { get; set; }
		public string active { get; set; }
	}
}

Open in new window

Which produces the following results -Capture.JPG-saige-
Bharath A.KAuthor Commented:
Hi saige,

     When I had tried the following code

JsonResponse response = JsonConvert.DeserializeObject<JsonResponse>((string)json.ToString());
        foreach (var detail in response.data)
        {
            Debug.WriteLine(detail.Value.member.email);
            Debug.WriteLine(detail.Value.Id.ToString());
            Debug.WriteLine(detail.Value.issue_date.ToString());
            Debug.WriteLine(detail.Value.member.email.ToString());
            Debug.WriteLine(detail.Value.amount_remaining.ToString());
        }

I get the following error when I access member,

{"Object reference not set to an instance of an object."}

Please suggest what is the problem?

With Many Thanks,
Bharath AK
it_saigeDeveloperCommented:
Look at your classes.  The properties in the class have to (at a minimum):

1.  Match the key portion of the json key/value pair object (or have a schema attribute that marks them as the recipient of a particular json key/value pair).
2.  Match the type that is being assigned from the json value (or have a converter defined that can convert from one type to another).

In your original class definitions, you have five properties that do not match your json schema (two by name, three by datatype).
public class JsonRewardResponse
{
    public Dictionary<int, JsonRewardDetails> mydictionary { get; set; }
}

public class JsonRewardDetails
{
	public JsonMemberDetails member;
	public int _store_details;
	public int _staff_details;
	public int product_details;
}

Open in new window

The dictionary property in JsonRewardResponse class maps to the *data* key in the Json string, not mydictionary.  So either change the property name to data or add a schema attribute to identify the correct mapping; e.g. -
public class JsonRewardResponse
{
	[JsonProperty(PropertyName = "data")]
	public Dictionary<int, JsonRewardDetails> mydictionary { get; set; }
}

Open in new window

The JsonMemberDetails property in JsonRewardDetails class maps to the *_member_details* key in the json string, not member.  Again we either change the property name to match the key or add a schema attribute to identify the correct mapping; e.g. -
[JsonProperty(PropertyName = "_member_details")]
public JsonMemberDetails member { get; set; }

Open in new window

Finally, the _store_details, _staff_details and product_details properties in the JsonRewardDetails class are all identified as integer types.  But the value of their keys is set to null.  The parser will throw an error because integers, by default, cannot be set as null.  In order to fix this, you can change their type to Nullable<int> (or int?), your can add a type converter or you can add an attribute that determines how to handle the null value; e.g. -
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int _store_details { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int _staff_details { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int product_details { get; set; }

Open in new window

Unlike the Property mapping, telling the parser how to handle null values, will affect the logic in your program.  What do I mean by this, well now the values for _store_details, _staff_details and product_details will be 0 instead of null (this is because 0 is the default value for the integer type).  Proof of concept -
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace EE_Q28829779
{
	class Program
	{
		static readonly string json = "{\"data\":{\"6\":{\"id\":\"6\",\"reward_definition_id\":12,\"person_id\":164305,\"issue_date\":\"2015-10-08\",\"expiry_date\":\"2015-11-08\",\"amount_initial\":20,\"amount_remaining\":0,\"_member_details\":{\"id\":\"164305\",\"first_name\":\"test\",\"last_name\":\"one\",\"email\":\"testing1@example.com\",\"_email_trigger\":\"Y\",\"_email_bounced\":\"N\",\"_email_promo\":\"Y\",\"_app_notify\":\"Y\",\"_sms_status\":\"Y\",\"active\":\"Y\"},\"_store_details\":null,\"_staff_details\":null,\"_product_details\":null},\"5\":{\"id\":\"5\",\"reward_definition_id\":12,\"person_id\":164305,\"issue_date\":\"2015-10-08\",\"expiry_date\":\"2015-11-08\",\"amount_initial\":20,\"amount_remaining\":20,\"_member_details\":{\"id\":\"164305\",\"first_name\":\"test\",\"last_name\":\"one\",\"email\":\"testing1@example.com\",\"_email_trigger\":\"Y\",\"_email_bounced\":\"N\",\"_email_promo\":\"Y\",\"_app_notify\":\"Y\",\"_sms_status\":\"Y\",\"active\":\"Y\"},\"_store_details\":null,\"_staff_details\":null,\"_product_details\":null}}}";

		static void Main(string[] args)
		{
			JsonRewardResponse response = JsonConvert.DeserializeObject<JsonRewardResponse>(json);
			foreach (var detail in response.mydictionary)
			{
				Console.WriteLine(detail.Value.member.email);
				Console.WriteLine(detail.Value.Id);
				Console.WriteLine(detail.Value.issue_date);
				Console.WriteLine(detail.Value.amount_remaining);
				Console.WriteLine(detail.Value._store_details);
				Console.WriteLine(detail.Value._staff_details);
				Console.WriteLine(detail.Value.product_details);
				Console.WriteLine();
			}
			Console.ReadLine();
		}
	}

	public class JsonRewardResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Dictionary<int, JsonRewardDetails> mydictionary { get; set; }
	}

	public class JsonRewardDetails
	{
		public string Id { get; set; }
		public int reward_definition_id { get; set; }
		public int person_id { get; set; }
		public string issue_date { get; set; }
		public string expiry_date { get; set; }
		public int amount_initial { get; set; }
		public int amount_remaining { get; set; }
		[JsonProperty(PropertyName = "_member_details")]
		public JsonMemberDetails member { get; set; }
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public int _store_details { get; set; }
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public int _staff_details { get; set; }
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public int product_details { get; set; }
	}
	public class JsonMemberDetails
	{
		public string Id { get; set; }
		public string first_name { get; set; }
		public string last_name { get; set; }
		public string email { get; set; }
		public string _email_trigger { get; set; }
		public string _email_bounced { get; set; }
		public string _email_promo { get; set; }
		public string _app_notify { get; set; }
		public string _sms_status { get; set; }
		public string active { get; set; }
	}
}

Open in new window

Produces the following output -Capture.JPG-saige-

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Bharath A.KAuthor Commented:
Thanks Saige for your help, everything resolved,

With Many Thanks,

Bharath AK
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JSON

From novice to tech pro — start learning today.