Deserialize JSON Stream with JSON.net - c#

I recently switched from using SOAP to JSON. I now have a problem with the performance because it takes about 26 seconds to deserialize the JSON stream on my WP7 device.
Therefore I thought about using Json.net instead of DataContractJsonSerializer.
However, I was not able to find much information about this.
I use a webclient and then OpenReadAsync, so I have a Stream as e.Result.
How can I turn that stream into an object using Json.net?
Should I maybe use DownloadStringAsync instead?
This is the Code that currently works:
//string URL = ""; //Actual URL to JSON is here
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri(URL, UriKind.Absolute));
And the event handler:
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JSONObject), null);
JSONObject data = serializer.ReadObject(e.Result) as JSONObject;
}
JSONObject is the response object of the service's SOAP endpoint, but both endpoints return the same data.
This works fine and I can go on and parse data just like I parsed the SOAP response, but I would like it do deserialize faster.

In order to deserialize you'll need the whole JSON. It may be better to use DownloadStringAsync and once you've received the entire JSON string, you can deserialize it.
Then in your DownloadStringCompleted you can pass in the class you want to deserialize it to. For example, if you are receiving JSON like:
{ name: "smoak", title: "super awesome" }
Then you need to create a class with those properties:
class SomeClassName
{
publc string name { get;set;}
public string title { get;set; }
}
and pass it to the JsonConvert:
var deserializedObj = JsonConvert.DeserializeObject<SomeClassName>(e.Result);
Console.WriteLine(deserializedObj.name);

Related

C# http-get url JSON data and parse it to text..?

I don't really know how to ask this but basically,
I have a url http://URL.com/filename.json
and I would like to fetch the data from /filename.json and "convert it to text".
The url file contains the following: {"CurrentVersion": "1.0"}
and I would like to get the CurrentVersion and define a string with its value (1.0).
One possibility is to make use of System.Net.WebClient for downloading the data: (Outdated, see Edit below.)
// WebClient is outdated
string json;
using(var webClient = new WebClient())
{
json = webClient.DownloadString("http://URL.com/filename.json");
}
after downloading the string you can deserialize it with a framework like Json.Net. Because it is a simple JSON file we can deserialize it into a dictionary. This way we do not have to create an explicit class for it:
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Now we can access the version like this:
var versionString = dict["CurrentVersion"];
Edit
Like #CodeCaster stated in the comments: The usage of System.Net.WebClient is outdated. Instead one should use System.Net.Http.HttpClient. Downloading the JSON could then look something like this:
// HttpClient is intended to be instantiated once per application, rather than per-use.
private readonly HttpClient _httpClient = new HttpClient();
[...]
var json = _httpClient.GetStringAsync("http://URL.com/filename.json");
// Do something with JSON

How to appropriately deserialize dynamic JSON?

I have a service that accepts JSON, and as a part of forwarding the requests from the Browser to a web server to the service (also an HTTP Server), I have this code:
if (Request.HttpMethod.ToLower() == "post")
{
var jsonObj = ObjectFromRequestBody<Dictionary<string, string>>();
if (jsonObj != null)
{
// uses Newtonsoft JSON Serializer to re-serialize the object; this is RestSharp
requestToForward.AddJsonBody(jsonObj);
}
}
ObjectFromRequestBody looks like this:
protected T ObjectFromRequestBody<T>()
{
Stream requestStream = Request.InputStream;
requestStream.Seek(0, SeekOrigin.Begin);
string json = new StreamReader(requestStream).ReadToEnd();
var payload = JsonConvert.DeserializeObject<T>(json);
return payload;
}
Now, this works fine, assuming that it -is- a JSON object being posted. (a KVP collection)
However, I imagine in the case that the payload is simply a value (int, string, boolean, or heck, even an array), this will error out.
I've tried simply deserializing to a type of Object results in it being re-serialized into an array of empty arrays; probably because Newtonsoft's JSON Serializer by default deserializes Objects to JObjects, which is essentially an enumerable of KVPs.
Is there a type agnostic way to get from Object to serializing to the appropriate type without essentially writing a series of conditional statements?
In this case a much better solution is to simply pipe the request body directly into the RestSharp request.
if (Request.HttpMethod.ToLower() == "post")
{
var requestBody = new StreamReader(Request.InputStream).ReadToEnd();
if (!string.IsNullOrWhiteSpace(requestBody))
{
request.AddHeader("Content-Type", "application/json");
request.AddParameter("", requestBody, RestSharp.ParameterType.RequestBody);
}
}
Though, would still be interested in hearing how to type-agnostically serialize a JObject properly.

RestSharp get serialized output

I am looking for a way to access the serialized result of the AddBody call.
I am using the built in RestSharp Serializer.
Example:
class Foo
{
public string FooField;
}
void SendRecord()
{
var f = new Foo();
f.FooField = "My Value";
request.AddBody(f);
// How do I get the serialized json result of the add body call without
// data? I would like to log the serialized output of the add body call to
// the database.
//Expected {"FooField":"My Value"}
var response = client.Execute(request);
}
I figured it out by finding this post.
request.Parameters.Where(p => p.Type == ParameterType.RequestBody).FirstOrDefault();
I also struggled with this (using v107 preview) and couldn't find any examples of logging the actual string sent to the server. The issue I was trying to debug was getting the right serialisation settings so the object was no use to me.
The only way I could find to get the serialized body as a string was to hook into the OnBeforeRequest event on the RestRequest:
var request = new RestRequest("/", Method.Post)
.AddHeader(KnownHeaders.ContentType, "application/json", false)
.AddJsonBody(myObj);
request.OnBeforeRequest = async (httpRequest) =>
{
var requestBodyStr = await httpRequest.Content.ReadAsStringAsync();
Trace.WriteLine($"Request body: {requestBodyStr}");
};
RestSharp itself doesn't expose the serialized request body when you pass an object to it.
There is a way to get at it though, I just posted over here:
https://stackoverflow.com/a/75537611/2509281
Right off the RestSharp homepage (http://restsharp.org/):
// execute the request
RestResponse response = client.Execute(request);
var content = response.Content; // raw content as string <~~~~~~~~~~

Using the contents of a JsonObject on aspx web page

I am trying to use a HTTP request to return the contents of a json string from google shopping api. What I have so far seems to be working but I would like to know how I can use the contents of the object to display the data on a page.
public string HttpGet(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
try
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream);
return reader.ReadToEnd();
}
}
finally
{
response.Close();
}
}
protected void submit_Click(object sender, EventArgs e)
{
string json = HttpGet("https://www.googleapis.com/shopping/search/v1/public/products?key={KEY}4&country=UK&q=BX80637153570K&rankBy=price:ascending&maxResults=1&alt=json");
dynamic obj = JsonObject.Parse(json);
}
Ok looking at the responses it looks as though I need a C# class for the data returned in json. I have created a classes using json2csharp.com. This is the data I need to return from the Json and display on the page. Maybe it will help explain my problem better.
https://www.googleapis.com/shopping/search/v1/public/products?key=AIzaSyCC0j59RBeGNtf2W2ft6avhfoTdJ1FQ2c4&country=UK&q=BX80637153570K&rankBy=price:ascending&maxResults=1&alt=json
Can anyone advise how I can use this information on my website. I am a little lost now as I'm new to all this and have tried several different methods.I don't need all of the returned data if that makes a difference? Just price and link.
Supposing dynamic obj is rightly filled you can use it's content in web page
For examples, if json is:
{
"error" : {
"code": 400,
"message": "Bad Request"
}
}
You can access object properties with code like this:
Response.Write("Error code is" + obj.error.code);
Of course Response.Write is only a sample on how you can send retrieved data to the page.
Edit 1:
It seems json converter used in question is not working or not working right.
In many cases, it's overkill to create a concrete class only to parse a json, expecially since C# 4 that can use ExpandoObject
This is a sample on how you can deserialize in a dynamic object without the need to create a concrete object
var url = "http://www.google.com/ig/calculator?hl=en&q=100USD=?EUR";
string json = HttpGet(url);
//this is json string:
//{lhs: "100 U.S. dollars",rhs: "78.1799703 Euros",error: "",icc: true}
//now convert in a dynamic object
var jss = new DynamicJsonConverter();
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
//now you have access to json content
string text1 = obj.lhs;
string text2 = obj.rhs;
DynamicJsonConverter class can be created using code you can find here:
Deserialize JSON into C# dynamic object?
I think you need to deserialize the response
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
You will need to create a class with the property resulted by the response.
Say test class
class Test
{
//define a similar property here
// which you suppose it will be return in the response
}
Then
Test routes_list = (Test)json_serializer.DeserializeObject(yourjson);
Edit 1
Or you can go through this link
How to Convert JSON object to Custom C# object?

Deserialize Json to Object in a handler

I have a simple class:
public class site
{
public string URL { get; set; }
}
That exists within a http handler. Currently I am posting json to this handler and trying to deserialize it to get the URL out of the string. I am however having a problem with the deserialize part of it.
I have a string "jsonString" that has the json formatted like so:
[{"URL":"http://www.google.com/etc/"}]
Here is my code for the deserialize:
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
string jsonString = String.Empty;
HttpContext.Current.Request.InputStream.Position = 0;
using (StreamReader inputStream = new StreamReader(HttpContext.Current.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
site currSite = new site();
currSite = jsonSerializer.Deserialize<site>(jsonString);
//set response types
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;
//send response
HttpContext.Current.Response.Write(jsonSerializer.Serialize(currSite.URL));
I am then trying to send a response using currSite.URL however it is failing. What am I missing here? I am reasonably confident it is at the deserialize part because if I send a response of jsonString instead of currSite.URL it will work.
Your json string shows that it's an array, not a single entity. You should deserialize it as so:
var result = jsonSerializer.Deserialize<site[]>(jsonString);
And result[0].Url should contain what you are looking for.
Update
Adding sample code:
string json = #"[{""URL"":""http://www.google.com/etc/""}]";
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<site[]>(json);
Console.WriteLine(result[0].URL);
Prints:
http://www.google.com/etc/
If you're simply trying to send back the URL as the response (just the string) there's no need to serialize the value. Just pass currSite.URL to the Write method.
Otherwise, I'm guessing you should serialize the whole currSite object for the response rather than just the URL. It all depends on what kind of response the caller is expecting (which you haven't specified).

Categories