DataContractJsonSerializer exception - c#

I am getting this error when using my class.
Error
Expecting element 'root' from namespace ''.. Encountered 'None' with
name '', namespace
My Class
[DataContract]
public class EntryData
{
[DataMember]
public string EntryId { get; set; }
[DataMember]
public string EmailAddress { get; set; }
[DataMember]
public string StatusCode { get; set; }
[DataMember]
public string TotalVoteCount { get; set; }
public static T Deserialise<T>(string json)
{
var obj = Activator.CreateInstance<T>();
using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
memoryStream.Position = 0;
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T)serializer.ReadObject(memoryStream); // getting exception here
return obj;
}
}
}
USAGE
string responseJson = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var results = EntryData.Deserialise<EntryData>(response)
I have seen online that it has to do with the memoryStream position BUT as you can see i am setting it to the beginning.
Please help.
Json going to handler
I don't set StatusCode or TotalVoteCount when passing JSON in. I don't think this is the problem though.
{
"EntryId":"43",
"EmailAddress":"test#email.com"
}
ANSWER
Instead of using Deserialize method in my class I am using now this.
//commented out this code.
string responseJson = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var results = EntryData.Deserialise<EntryData>(response)
// this is the way to go using JavaScriptSerializer
var serializer = new JavaScriptSerializer();
var results = serializer.Deserialize<EntryData>(response);

Could it be caused by your JSON names not matching your property names in C#?
My understanding is that
{
"FirstName" : "Mark"
}
Would be able to deserialize into:
[DataContract]
public class Person
{
[DataMember]
public string FirstName {get; set;}
}
but this wouldn't be able to serialize
{
"Name" : "Mark"
}
unless you changed your C# class to have an explicit name for the DataMember
[DataContract]
public class Person
{
[DataMember(Name="Name")]
public string FirstName {get; set;}
}
I'm not sure which error this would cause though. I Don't have enough first hand experience.

Do you think it could be an encoding problem? Have you tried using Encoding.UTF8 instead of Unicode?
All the examples I have seen using DataContractSerializer have used a UTF-8 encoding.
Encoding.Unicode is a UTF-16 encoding.
I can't find any documentation explicitly stating which encodings DataContractSerializer supports. I assume it would be smart enough to detect the proper encoding, but I don't know a whole whole lot about encodings. Maybe that isn't really possible in this instance.

Related

Windows App - Using XML in textbox

[DataContract]
public class RootObject
{
[DataMember]
public int RecipeID { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public string Cuisine { get; set; }
[DataMember]
public string Category { get; set; }
[DataMember]
}
public async static Task<RootObject> GetRecipe()
{
var http = new HttpClient();
var url = String.Format("http://api.bigoven.com/recipe/196149?api_key=//apikey");
var response = await http.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
XmlSerializer serializer = new XmlSerializer(typeof(RootObject));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
XmlReader reader = XmlReader.Create(ms);
RootObject i;
i = (RootObject)serializer.Deserialize(reader);
return i;
}
I use the above method in a bigoven class which gets the data of a recipe as XML data such as:
<Recipe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RecipeID>196149</RecipeID>
<Title>Lasagna</Title>
<Cuisine>Italian</Cuisine>
and I would like to put the data for the title and cuisine into textboxes, however when I try the method below I get the error "Recipe xmlns='' was not expected."
RootObject myRecipe = await bigoven.GetRecipe();
textBox.Text = myRecipe.Title;
Answered before. Basically this:
When serialising an XML document to a .NET string, the encoding must be set to UTF-16. Strings are stored as UTF-16 internally, so this is the only encoding that makes sense. If you want to store data in a different encoding, you use a byte array instead.
See the entire thread here:
Using StringWriter for XML Serialization
It looks like your Json serializer might be trying to deserialize xml data.
You might try looking at the raw string in result and making sure that it's actually JSON data. If it's not, you need to find the appropriate deserailizer to use.
I'm guessing result contains XML in which case you'd need to use an XML Deserializer to convert it to a RootObject
Here's the link for the .NET one:
https://msdn.microsoft.com/en-us/library/tz8csy73(v=vs.110).aspx

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.

JSON Object to properties

I want to store the results from JSON in properties, but I don't know how. I'm using ASP.NET with MVC 4/Razor.
My model's constructor is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
JObject _naturalUserObject = (JObject)JsonConvert.DeserializeObject(response);
}
And I have the follow properties:
[Key]
public int Id { get; set; }
public int DisplayName { get; set; }
public int Avatar { get; set; }
To access a simple value from my JSON:
_naturalUserObject["users"][0]["name"];
The final question is: how can I store each value from my JObject in my model's properties and finally display it into my view?
Thanks in advance.
/EDIT/
My model now is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(String.Format("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}", ConfigurationManager.AppSettings["SteamApiKey"].ToString(), HttpContext.Current.Request.Cookies["SteamIdCookie"].Value));
string _naturalUserObject = JsonConvert.DeserializeObject<string>(response);
}
And one of my property is:
private string _avatar;
public string Avatar
{
get { return _avatar; }
set { _avatar = _naturalUserObject["response"]["players"][0]["avatar"]; }
}
But without success. =(
Lets say you have the following Json
string yourJsonString = "{\"FIRST_NAME\":\"Foo\",\"LAST_NAME\":\"Bar\"}";
You could model this Json as:
public class JsonModel
{
[JsonProperty("FIRST_NAME")]
public string FirstName {get; set;}
[JsonProperty("LAST_NAME")]
public string LastName {get; set;}
}
Note that you can use JsonPropertyAttribute to tell Json.Net what the property's corresponding json field is.
Now, that you have your model set up, can use JsonConvert.DeserializeObject<T>(...) to get a strongly typed instance of your json model.
JsonModel jsonModel = JsonConvert.DeserializeObject<JsonModel>(yourJsonString);
string firstName = jsonModel.FirstName; // Foo
string lastName = jsonModel.LastName; // Bar
As someone had mentioned, if you do it this way, you won't have to deal with JObject and moreover, it will force you to actually understand the structure of the json being returned.
Specifically in your example, you could store an object of type JsonModel and in your model's constructor initialize it using JsonConvert.DeserializeObject<T>. Your public properties could then just call into that JsonModel instance and get the appropriate values.
Here's a more detailed example. Assume you are getting back the json I had provided above and are using the same model we created before. Let's say you have a private field in your class of type JsonModel
private JsonModel jsonModel;
You can initialize it in your constructor:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
jsonModel = JsonConvert.DeserializeObject<JsonModel>(response);
}
Now, your public properties can simply call into this JsonModel object.
public string FirstName
{
get { return jsonModel.FirstName; }
set { jsonModel.FirstName = value; }
}
I recommend ServiceStack.Text (available as a standalone NuGet package install, without the rest of the framework if you don't need it).
This adds two nice extension methods:
public class MyPOCO
{
public string Name {get; set; }
public int Age {get; set; }
}
And later:
string json = myPocoInstance.ToJson();
and:
MyPOCO instance = jsonString.FromJson<MyPOCO>();
Very fast too!
If you use Json.net you can deserialize directly into a clr object (which could be your viewmodel or model), you won't have to deal with JObject.
JsonConvert.DeserializeObject<myviewmodelormodel>(myjsondata);
If you get the object back as a string in JSON format. You can use the JSON de-serializer like this:
Put this into a static class this will become an extension method to all strings
public static T Deserialize<T>(this string json)
{
var obj = Activator.CreateInstance<T>();
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T) serializer.ReadObject(ms);
}
return obj;
}
EX:
this calls a url getting the result set in a string, then calls the
extension method to return an object.
the url returns MyPOCO
var stringValue = HttpGet(url);//how you get the value from a web service call
var myUserModel = stringValue.Deserialize<MyPOCO>();

DataContractJsonSerializer returning null object

I've been struggling with this problem for quite some time now, and can't solve it.
I have the following JSON string:
{"Search":[{"Title":"somestring","Year":"somestring","imdbID":"somestring"}]}, {"Title":"somestring","Year":"somestring","imdbID":"somestring"} etc
The string can repeat itself multiple times, so I want to store the values in a list. In order to do this I've created the following two classes:
The SuggestionListener class:
[DataContract]
class SuggestionLister
{
public List<MovieResults> suggestionlist {get;set;}
}
Which holds the List I want returned.
And the Movieresults class:
[DataContract]
class MovieResults
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string Year { get; set; }
[DataMember]
public string imdbID { get; set; }
}
Which hold the data that needs to be stored. I tried Deserializing it with the following code:
byte[] data = Encoding.UTF8.GetBytes(resp);
MemoryStream memStream = new MemoryStream(data);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SuggestionLister));
SuggestionLister suggestionMovies = (SuggestionLister)serializer.ReadObject(memStream);
Where the 'resp' variable is the JSON string. However, when I try this code the suggestMovies object remains null. What is wrong?
Okay so there are a couple of issues:
[DataContract]
public class SuggestionLister
{
[DataMember]
public List<MovieResults> Search { get; set; }
}
You do not have DataMember attribute on your list property and it needs to match the name of the array value which is "Search".
Edit: I tested all of this using your code. Also the format of your JSON that you posted is not correct, but I am assuming that is a pasting error.
Try
[DataContract]
class SuggestionLister
{
public List<MovieResults> Search {get;set;}
}
Since your json seems to be of this format:
{
"Search": [ { "Title": ... }]
}

deserialize POCO array with JsonFX

I want to simply read some JSON data from a URL, then turn that into an collection of POCO classes, but I can't seem to figure out what I'm doing wrong.
Here is a sample of the JSON data, as it is fetched from the URL:
[
{
"Name":"Together As One Run",
"Location":"Parkville, MO",
"ScheduledAt":"\/Date(1334984400000)\/",
"URL":"http://www.runningintheusa.com/Race/View.aspx?RaceID=36667"
},
{
"Name":"Lean Green Running Machine 5K Run/Walk and 1 Mile Run",
"Location":"Springfield, MO",
"ScheduledAt":"\/Date(1335589200000)\/",
"URL":"http://www.runningintheusa.com/Race/View.aspx?RaceID=53945"
},
{
"Name":"Festival of Miles",
"Location":"St. Louis, MO",
"ScheduledAt":"\/Date(1338440400000)\/",
"URL":"http://www.runningintheusa.com/Race/View.aspx?RaceID=53901"
},
{
"Name":"Miles Against Melanoma",
"Location":"Saint Charles, MO",
"ScheduledAt":"\/Date(1338613200000)\/",
"URL":"http://www.runningintheusa.com/Race/View.aspx?RaceID=53939"
}
]
I can get this data with WebClient just fine.
I'm setting up my JsonFX reader like this:
var json = new JsonReader(new DataReaderSettings(new PocoResolverStrategy()));
Here is my POCO class:
public class Race {
public String Name { get; set; }
public String Location { get; set; }
public DateTime ScheduledAt { get; set; }
public String URL { get; set; }
}
I have tried to deserialize JSON data in several ways, and nothing seems to work:
//reader is an instance of StreamReader
var content = reader.ReadToEnd();
//nope
//var output = json.Read<Race>(content);
//nope
//var output = json.Read<Race[]>(content);
This has got to be a simple thing to do, I just can't find a solution. I spent about 30 mins. googling to no avail. Any help would be appreciated!
I've never used JsonFX but you can try Json.Net or built-in JavaScriptSerializer. Both work without any problem.
var jObj1 = JsonConvert.DeserializeObject<Race[]>(jsonstr);
var jobj2 = new JavaScriptSerializer().Deserialize<Race[]>(jsonstr);
edit oops, didn't read the title. Why are you using jsonfx?
maybe try a list?
var output = json.Read<List<Race>>(input);
Here is a valid example of how to get it done with JSON.Net.
You're going to want to use JSON.NET. It's faster than any of the built in classes and does a much better job of serializing dictionaries.
using Nuget
> Install-Package Newtonsoft.Json
List<Race> deserializedRaces = JsonConvert.DeserializeObject<List<Race>>(jsonString);
I bet you need to specify the datacontract and datamember attributes on your custom type for jsonFX to recognize it.
using System.Runtime.Serialization;
[DataContract]
public class Race {
[DataMember]
public String Name { get; set; }
[DataMember]
public String Location { get; set; }
[DataMember]
public DateTime ScheduledAt { get; set; }
[DataMember]
public String URL { get; set; }
}
You probably need to tell it to try parsing your date as a Microsoft-style date time:
var jsonReader = new JsonReader(
new DataReaderSettings(
new PocoResolverStrategy(),
new MSAjaxDateFilter()));

Categories