How to parse multiple records in Json - c#

Hello I am trying to parse a Json response into a class. So here is how the response looks...
[{"id":103,"customer_id":0},{"id":110,"customer_id":1}]
I was able to parse one line okay (I removed the '[' ']' and put it into one class). The problem is when I have multiple records, like this, that I am having an issue. This is how I am parsing the data...
[DataContract]
public class Order
{
public List<OrderRow> Orders { get; set; }
}
[DataContract]
public class OrderRow
{
[DataMember(Name = "id")]
public int id { get; set; }
[DataMember(Name = "customer_id")]
public int customer_id { get; set; }
}
StreamReader jfile = new StreamReader(#"path\test.json");
string json = jfile.ReadToEnd();
jfile.Close();
byte[] bytes = Encoding.UTF8.GetBytes(json);
MemoryStream mStream = new MemoryStream(bytes);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Order));
Order jsonOrder = (Order)serializer.ReadObject(mStream);

Instead of creating Order class, try to deserialize it directly into OrderRow[] array:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(OrderRow[]));
OrderRow[] jsonOrderRows = (OrderRow[])serializer.ReadObject(mStream);

Related

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();
}
}

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.

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...)

I can't decrypt text

I have url http://translate.google.ru/translate_a/t?client=x&text=ввійти вийти&sl=ua&tl=en
If you will go through this link in response you will have js file with normal translate text:
{"sentences":[{"trans":"enter exit","orig":"ввійти вийти","translit":"","src_translit":"vviy̆ty vyy̆ty"}],"src":"uk","server_time":127}
But if you get this data through program you will have encrypt translate data:
{"sentences":[{"trans":"\u00D0 \u00B2 \u00D0 \u00B2 \u00D1-\u00D0 \u00B9 \u00D1,
\u00D0 \u00B8 \u00D0 \u00B2 \u00D0 \u00B8 \u00D0 \u00B9 \u00D1, \u00D0 \u00B8",
"orig":"\u00D0\u00B2\u00D0\u00B2\u00D1?\u00D0\u00B9\u00D1?\u00D0\u00B8 \u00D0\u0
0B2\u00D0\u00B8\u00D0\u00B9\u00D1?\u00D0\u00B8","translit":"","src_translit":""}
],"src":"is","server_time":4}
Through this code i got this data.
string url = #"http://translate.google.ru/translate_a/t?client=x&text=ввійти вийти&sl=ua&tl=en";
WebRequest request = WebRequest.Create(url);
request.Timeout = 5000;
WebResponse responce = request.GetResponse();
Stream stream = responce.GetResponseStream();
StreamReader st = new StreamReader(stream);
string responsText = st.ReadToEnd();
Console.WriteLine(responsText);
Console.ReadLine();
How can i decrypt this data?
The data is not encrypted. It is encoded. If you use proper JSON deserialization, like the DataJsonContractSerializer class, this will not be a problem, because the framework will decode the data for you.
[DataContract]
public class TranslationData {
[DataMember(Name = "sentences")]
public Sentence[] Sentences { get; set; }
[DataMember(Name = "src")]
public string Source { get; set; }
[DataMember(Name = "server_time")]
public int ServerTime { get; set; }
}
[DataContract]
public class Sentence {
[DataMember(Name = "trans")]
public string Translation { get; set; }
[DataMember(Name = "orig")]
public string Original { get; set; }
[DataMember(Name = "translit")]
public string Transliteration { get; set; }
[DataMember(Name = "src_translit")]
public string SourceTransliteration { get; set; }
}
Then use the System.Runtime.Serialization.Json.DataContractJsonSerializer class for deserialization (you have to add a reference to the System.Runtime.Serialization assembly) to read from the response stream directly:
var serializer = new DataContractJsonSerializer(typeof(TranslationData));
return (TranslationData)serializer.ReadObject(theResponseStream);
There are other ways of doing this, but this way you'll get nice typed data.

Categories