Missing JSON field causes crashes? - c#

My Code goes like this:
using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream()))
{
string resultString = streamReader1.ReadToEnd();
var ser = new DataContractJsonSerializer(typeof(RootObject));
var stream = new MemoryStream(Encoding.Unicode.GetBytes(resultString));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));
RootObject myBook = (RootObject)jsonSerializer.ReadObject(stream);
Deployment.Current.Dispatcher.BeginInvoke(() => Shops.ItemsSource = myBook.SearchResponse.Spell.Results); }
public class Query
{
public string SearchTerms { get; set; }
}
public class Result
{ [DataMember(IsRequired=false)]
public string Value { get; set; }
}
public class Spell
{
[DataMember(IsRequired = false)]
public int Total { get; set; }
[DataMember(IsRequired = false)]
public List<Result> Results { get; set; }
}
public class SearchResponse
{
public bool IsRequired { get; set; }
public string Version { get; set; }
public Query Query { get; set; }
public Spell Spell { get; set; }
}
public class RootObject
{
public SearchResponse SearchResponse { get; set; }
}
IF JSON DATA EXISTS
{"SearchResponse":{"Version":"2.0","Query":{"SearchTerms":"mispell"},"Spell":{"Total":1,"Results":[{"Value":"misspell"}]}}}
IF JSON DATA DOES NOT EXIST
{"SearchResponse":{"Version":"2.0","Query":{"SearchTerms":"mispel"}}}
The thing is, if Bing doesn't detect a wrong word, it crashes and gives me an error like NullReferenceException. I have tried to do an IF statement looking at the stream for if it's value is blank but doesn't seem to work.
Any ideas?

If you receive a JSON answer without the Spell part, the Spell property in SearchResponse will be null. If it's null, you may not dereference it like this:
myBook.SearchResponse.Spell.Results
(This hasn't anything to do with JSON. It's how C# works.)
So instead of:
Shops.ItemsSource = myBook.SearchResponse.Spell.Results
you probably want to write:
if (myBook.SearchResponse.Spell = null)
Shops.ItemsSource = myBook.SearchResponse.Spell.Results;
else
Shops.ItemsSource = new List<Result>();
For your next question: It would be very helpful if your questions would show the exact error message including the stack trace (or at least the exact line where it occurred).

Use [DataMember(IsRequired=false)], MSDN: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.isrequired.aspx

Related

Json.Net Deserializing list of c# objects throwing error

I have a list of objects in below json format. I would like to deserialize using below code. It is throwing unable to convert to object error. I have tried below three options, but didnt help. jsoninput is a IEnumerable<string>converted into json object using ToJson().
Error:
{"Error converting value \"{\"id\":\"11ef2c75-9a6d-4cef-8163-94daad4f8397\",\"name\":\"bracing\",\"lastName\":\"male\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false,\"userType\":0,\"profilePrivacy\":1,\"chatPrivacy\":1,\"callPrivacy\":0}\" to type 'Api.Models.UserInfo'. Path '[0]', line 1, position 271."}
var requests1 = JsonConvert.DeserializeObject<UsersInfo>(jsoninput);
var requests2 = JsonConvert.DeserializeObject<IEnumerable<UserInfo>>(jsoninput);
var requests3 = JsonConvert.DeserializeObject<List<UserInfo>>(jsoninput);
//Below are my classes,
public class UsersInfo
{
public List<UserInfo> UserInfoList { get; set; }
public UsersInfo()
{
UserInfoList = new List<UserInfo>();
}
}
public class UserInfo
{
public string Id { set; get; }
public string Name { set; get; }
public string LastName { set; get; }
public string ProfilePictureUrl { set; get; }
public string SmallUrl { set; get; }
public string ThumbnailUrl { get; set; }
public string Country { set; get; }
public bool IsInvalid { set; get; }
}
Below is my json object,
["{\"id\":\"11ef2c75-9a6d-4cef-8163-94daad4f8397\",\"name\":\"bracing\",\"lastName\":\"male\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false}","{\"id\":\"318c0885-2720-472c-ba9e-1d1e120bcf65\",\"name\":\"locomotives\",\"lastName\":\"riddles\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false}"]
Looping through individual items in json input and if i deserialize it like below, it works fine. But i want to deserialize the list fully. Note: jsoninput was a IEnumerable<string> before i convert in json object.
foreach (var re in jsoninput)
{
var request0 = JsonConvert.DeserializeObject<UserInfo>(re);
}
Please look at this fiddle: https://dotnetfiddle.net/XpjuL4
This is the code:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
//Below are my classes,
public class UsersInfo
{
public List<UserInfo> UserInfoList { get; set; }
public UsersInfo()
{
UserInfoList = new List<UserInfo>();
}
}
public class UserInfo
{
public string Id { set; get; }
public string Name { set; get; }
public string LastName { set; get; }
public string ProfilePictureUrl { set; get; }
public string SmallUrl { set; get; }
public string ThumbnailUrl { get; set; }
public string Country { set; get; }
public bool IsInvalid { set; get; }
}
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
Option1();
Option2();
}
public static void Option1(){
string json = #"{""UserInfoList"":[
{""id"":""11ef2c75 - 9a6d - 4cef - 8163 - 94daad4f8397"",""name"":""bracing"",""lastName"":""male"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false},
{ ""id"":""318c0885-2720-472c-ba9e-1d1e120bcf65"",""name"":""locomotives"",""lastName"":""riddles"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false}
]}";
var obj = JsonConvert.DeserializeObject<UsersInfo>(json);
obj.UserInfoList.ForEach(e => Console.WriteLine(e.Id));
}
public static void Option2(){
string json = #"[
{""id"":""11ef2c75 - 9a6d - 4cef - 8163 - 94daad4f8397"",""name"":""bracing"",""lastName"":""male"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false},
{ ""id"":""318c0885-2720-472c-ba9e-1d1e120bcf65"",""name"":""locomotives"",""lastName"":""riddles"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false}
]";
var obj = JsonConvert.DeserializeObject<List<UserInfo>>(json);
obj.ForEach(e => Console.WriteLine(e.Id));
}
}
Both work, and are basically very close to what you are doing. You can either serialize it as a list (based on your json, I think that's the closest to your use case, and that's Option 2).
However, put extra attention to the JSON. I had to re-parse your JSON to make it work (https://jsonformatter.org/json-parser is a nice website to do it). For the sake of explaining the example, in C#, # means raw string, and in raw string, quotes are escaped with double quotes "".
I would expect that the business logic generating this JSON is not correct, if the JSON you pasted is the direct result from it.
EDIT
Given the OP's comment:
Thanks Tu.ma for your thoughts. The other method returns
IEnumerable which is nothing but
Dictionary.Where(x => x.Value == null).Select(x =>
x.Key).ToHashSet(). The values in Dictionary are -> Key
is String, Value is UserInfo object serialized. So, in that case i
should deserialize one by one? If not, i should serialize entire list
in one shot? Am i right? – Raj 12 hours ago
The problem is in the way you are generating the list of UsersInfo. The result from Dictionary<string,string>.Where(x => x.Value == null).Select(x =>
x.Key).ToHashSet() is a bunch of strings, not of objects, so you need to serialize them one by one.
If you are worried about the linearity of the approach, you could consider running through it in parallel. Of course, you need to judge if it fits your application.
var userInfoStrings = Dictionary<string,string>.Where(x => x.Value == null).Select(x => x.Key).ToHashSet();
var UserInfoList = userInfoStrings.AsParallel().Select (u => JsonConvert.DeserializeObject<UsersInfo>(u)).ToList();

Issue with Deserialization with JSON with C#

I have looked over example after example after example and none of my attempts have worked.
I'm attempting to deserialize this JSON return:
{
"status": "success",
"data": {
"result": "match",
"id_user": 26564,
"dob_match": null,
"first_name_match": null,
"last_name_match": null
},
"code": 200
}
Here is my JSON object class declaration:
[DataContract]
internal class DccCoachApi
{
[DataMember]
public string result { get; set; }
public string id_user { get; set; }
public string dob_match { get; set; }
public string first_name_match { get; set; }
public string last_name_match { get; set; }
}
In my stream method, my streamRead variable is filled with:
{"status":"success","data":{"result":"match","id_user":26564,"dob_match":null,"first_name_match":null,"last_name_match":null},"code":200}
Method 1 does not populate coachId:
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(streamRead)))
{
// Deserialization from JSON
var deserializer = new DataContractJsonSerializer(typeof(DccCoachApi));
var dccObj = (DccCoachApi)deserializer.ReadObject(ms);
coachId = dccObj.id_user;
}
Nor does method 2:
DccCoachApi coach = new JavaScriptSerializer().Deserialize<DccCoachApi>(streamRead);
coachId = coach.id_user;
nor does method 3:
JavaScriptSerializer js = new JavaScriptSerializer();
DccCoachApi dccObj = js.Deserialize<DccCoachApi>(streamRead);
coachId = dccObj.id_user;
nor does method 4:
dynamic dccObject = js.Deserialize<dynamic>(streamRead);
coachId = dccObject["id_user"];
The hard error that gets produced when i pull the value directly off method 4 is:
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
Methods 1-3 do not hit a hard error, however they populate coachId with no data.
Can somebody please let me know what i'm doing wrong?
You can simply generate proper classes here: http://json2csharp.com/
This is how it should look like you don't need the DataMember Attributes, it might confuse the serializer to only de-serialize this single property:
public class Data
{
public string result { get; set; }
public int id_user { get; set; }
public object dob_match { get; set; }
public object first_name_match { get; set; }
public object last_name_match { get; set; }
}
public class RootObject
{
public string status { get; set; }
public Data data { get; set; }
public int code { get; set; }
}
Code:
var deserializer = DataContractJsonSerializer(typeof(RootObject));
var root = (RootObject)deserializer.ReadObject(ms);
var coachId = root.data.id_user;
I revised the code to look like this, and it is dumping my value perfectly. Thanks much to everyone who helped me reach the solution. Plutonix, thanks as well for the paste special 411. I had no idea that existed. VERY useful!
using (var reader = new StreamReader(webResponse.GetResponseStream()))
{
var streamRead = reader.ReadToEnd();
reader.Close();
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(streamRead)))
{
JavaScriptSerializer js = new JavaScriptSerializer();
DccCoachRootobject dccObj = js.Deserialize<DccCoachRootobject>(streamRead);
coachId = dccObj.data.id_user.ToString();
}
}

c# JSONConvert.DeserializeObject<List<RootObject>> returns nulls

I am trying to deserialize an HTTPWebRequest response (Json) to a c# object/class, but am having trouble. A collection with 10 instances of the object are returned, and all the objects are null.
Here is the json:
[
{
"id":2227,
"user_id":441,
"grades":
{"html_url":"https://...",
"current_score":91.26,
"current_grade":null,
},
"sis_account_id":"11",
"user":
{"id":441,
"name":"Nicholas Bailey",
}
},
Here are the classes:
public class Grade
{
public string html_url { get; set; }
public decimal current_score { get; set; }
public string current_grade { get; set; }
}
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class Enrollment
{
public int id { get; set; }
public int user_id { get; set; }
public Grade grades { get; set; }
public string sis_account_id { get; set; }
public User user { get; set; }
}
public class RootObject
{
public Enrollment enrollment { get; set; }
}
And here is my code:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://(some uri)");
WebResponse response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
string content = sr.ReadToEnd();
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
var outObject = JsonConvert.DeserializeObject<List<RootObject>>(content, settings);
I have been looking at a lot of code on google but have not found a situation that is close to mine. Also, I'm a bit green on generic collections. The code runs fine but in the debugger the "outObject" contains 10 entries, each with an "Enrollment" object that is null.
I also have tried this with json that has well over 10 entries, but it still comes up with 10. But I'm more focused on the nulls at this point (One thing at a time!). For the sake of brevity I have removed several entries in the json, but the main pattern (an enrollment object with a grades object and a user object embedded in it) remains.
Any help would be much appreciated. Thanks.
Deserialize to List<Enrollment> not List<RootObject>:
var enrollment = JsonConvert.DeserializeObject<List<Enrollment>>(content, settings);
The first JSON object in the root array has properties "id", "user_id" and so on that correspond to the members of Enrollment. Conversely there is no property "enrollment" in the JSON anywhere.
Sample fiddle.
Update
You asked, I tried this and now I'm getting an exception "Error converting value {null} to type 'System.Int32'. Path '[0].associated_user_id', line 1, position 165." associated_user_id was removed for brevity but I will add it back into my code. Any ideas?
Somewhere your data model you must have the following member (field or property):
public int associated_user_id;
Change this to a nullable:
public int? associated_user_id;

C# GET REST xml to object deserialization encoding clash

I wanna get xml file from http and convert it to object.
So right now I have 2 methods: one to get http response body like that:
var httpClient = new HttpClient();
var op = httpClient.GetStringAsync(uri);
var httpResponseBody = "";
try {
var httpResponse = await httpClient.GetAsync(uri);
httpResponse.EnsureSuccessStatusCode();
httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
return httpResponseBody;
}
...
which returns string httpResponseBody.
Second one tries to convert this xml in string to object:
res = await task;
var reader = new XmlSerializer(typeof(Schedule));
using (var tr = new MemoryStream(Encoding.UTF8.GetBytes(res)))
{
var schedule = (Schedule)reader.Deserialize(tr);
return schedule;
}
The problem is that the content I receive is in different encoding and I don't know how to convert it to make deserialization possible.
I am getting something like this:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ramowka><dzien name=\"PoniedziaÅ\u0082ek\" count=\"2\"/></ramowka>\n
How to get rid of '\n' and Å\u0082 (should be ł) ?
Right now I am getting Exception from reader.Deserialize: {"<ramowka xmlns=''> was not expected."}
Schedule class:
[XmlType(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = false)]
public class Schedule
{
[XmlElementAttribute("ramowka")]
public ScheduleDay[] AuditionDays { get; set; }
}
I've changed Schedule class to:
[XmlType(AnonymousType = true)]
[XmlRootAttribute("ramowka")]
public class Schedule
{
[XmlElementAttribute("dzien")]
public ScheduleDay[] AuditionDays { get; set; }
}
Now it looks like working. Thanks Petter for hint with Root attribute.
Setting the root object on the XmlSerializer fixes the problem:
var reader = new XmlSerializer(typeof(Schedule), new XmlRootAttribute("ramowka"));
...though I used slightly different attributes:
[DataContract]
public class ScheduleDay
{
[DataMember, XmlAttribute]
public string name { get; set; }
[DataMember, XmlAttribute]
public string count { get; set; }
}
[DataContract]
public class Schedule
{
[DataMember]
public ScheduleDay dzien { get; set; }
}
I haven't tried yours yet, but these work.
For a collection of ScheduleDays, this combo works:
[XmlType("dzien")]
public class ScheduleDay
{
[XmlAttribute]
public string name { get; set; }
[XmlAttribute]
public string count { get; set; }
}
Usage:
XmlSerializer reader = new XmlSerializer(typeof(List<ScheduleDay>), new XmlRootAttribute("ramowka"));
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(Xml)))
{
List<ScheduleDay> schedule = (List<ScheduleDay>)reader.Deserialize(stream);
}
The Schedule class just disappeared from the equation.
Escapes in the HTML
The \ns are part of the XML structure, so no need to worry about those. The deserializer will translate \u0082 into its equivalent character, which is
BREAK PERMITTED HERE. Which you probably don't want. The Å looks out of place too -- it's the last letter of the Norwegian alphabet and not used in Polish, AFAIK.

Metro App - deserialize JSON String

I'd like to deserialize a JSON string which I get from a webservice. My problem is, that the deserialized object class array (of type Result) has always 0 items in it....
But the webservice returns the correct string.
So I think the failure occurs in the way how I deserialize the string/stream.
Any ideas what's my fault?
//JSON result string:
{"Results":
[{"Result":{
"Name":"Rechnung2",
"Date1":"2012-10-05",
"Item1":"50",
"Item2":"10",
"CompanyName":"Contoso",
"Description":"My description"}}]
}
[DataContract]
public class Result
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Date1 { get; set; }
[DataMember]
public string Item1 { get; set; }
[DataMember]
public string Item2 { get; set; }
[DataMember]
public string CompanyName { get; set; }
[DataMember]
public string Description { get; set; }
}
public async void GetjsonStream()
{
HttpClient client = new HttpClient();
string url = "http://localhost/test/api.php?format=json&key=12345";
HttpResponseMessage response = await client.GetAsync(url);
//ReadAsStringAsync() works fine, so I think ReadAsStreamAsync() works also fine
var str = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Result[]));
//Result has always 0 items
Result[] res = (Result[])ser.ReadObject(str);
}
I haven't used DataContractJsonSerializer myself, so this may not be the best approach - but I suspect that the problem is that the JSON represents "an object containing a collection of results" - not "a collection of results".
Try this, in addition to your existing code:
[DataContract]
public class ResultCollection
{
[DataMember]
public Result[] Results { get; set; }
}
...
var ser = new DataContractJsonSerializer(typeof(ResultCollection));
var collection = (ResultCollection)ser.ReadObject(str);
var results = collection.Results;
You may be able to change the type of Results to List<Result> too, if that's helpful.
(I've just tried the code above, and it gave me the right result, so it looks like this is at least along the right lines...)

Categories