Retrieve JSON value with random generated value - c#

I've got a JSON file that looks like this. It's basically a JSON file taken stright from Wikipedia using their API.
{
"batchcomplete": "",
"query": {
"pages": {
"31329803": {
"pageid": 31329803,
"ns": 0,
"title": "Wiki Title",
"extract": "<p><b>Your Wiki Title</b></p>"
}
}
}
}
The number generated under "pages" (which is the pageID) is random. I'm trying to retrieve the "extract" value, but I can't seem to get it.
I'm using Visual Studio & using NewtonSoft JSON.net for parsing. I've created a class for retrieving the data I want, and it looks like this.
public class WikiPage
{
public string title { get; set; }
public int pageid { get; set; }
public int ns { get; set; }
public string extract { get; set; }
}
I'm trying to bypass the JSON tree & get the value I want. The code I use to get the value are as follows:
static void Main(string[] args)
{
// Getting JSON string from file
string JSONString = File.ReadAllText("wiki.json");
JObject wikiSearchResult = JObject.Parse(JSONString);
IList<JToken> wikiPages = wikiSearchResult["query"]["pages"].Children().ToList();
JToken result = wikiPages[0];
var wp = JsonConvert.DeserializeObject<WikiPage>(result.ToString());
// Writing data
Console.WriteLine(wp.extract);
Console.ReadLine();
}
When I run the program program, I get an error:
An unhandled exception of type
'Newtonsoft.Json.JsonSerializationException' occurred in
Newtonsoft.Json.dll
Additional information: Error converting value "31329803" to type
'JSON_test.WikiPage'. Path '', line 1, position 10.
I've tried many things, but no luck. Maybe there is a simpler way to do it, but I'm pretty much stuck right now, can someone help me?

You're almost done, just get result this way:
JToken result = wikiPages[0].Children().First();

You can't deserialize a key value pair like that. Try this instead :
var json = JObject.Parse(JSONString);
var pages = json["query"]["pages"].ToObject<Dictionary<string, WikiPage>>();
var page = pages.First().Value;
Console.WriteLine(page.extract);

Related

How can I loop through the JSON on Universal Windows Platform with C#

I am developing an app on UWP.
When I connect with a server api and I get the next response I don't have problems.
{"value":"Login successfull","sessionId":"a95077855b05ed0fec5d7fa3abafa126e15aba2a"}
I can get information in the following way:
JsonObject jsonObject = JsonObject.Parse(jsonString);
string token = jsonObject["sessionId"].GetString();
string value = jsonObject["value"].GetString();
but my problem is when i get the next response of the api:
[{"person":{"name":"name1","country":"Spain","city":"user_city","phone":null}},{"person":{"name":"name2","country":"Turkey","city":"user_city","phone":"1111111"}},{"person":{"name":"name3","country":"Argentina","city":"user_city","phone":"22222"}},{"person":{"name":"name4","country":"Argentina","city":"user_city","phone":"33333"}}]
How can I loop through the JSON and get all the people that match a condition?
I have to do with "Windows.Data.Json"
If interested in a solution using only Windows.Data.Json namespace, here it is:
var rootValue = JsonValue.Parse(jsonString);
foreach (var item in rootValue.GetArray())
{
var unamedObject = item.GetObject();
var personObject = unamedObject["person"].GetObject();
System.Diagnostics.Debug.WriteLine(personObject["name"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["country"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["city"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["phone"].GetString());
}
Why would somebody pick Windows.Data.Json over Newtonsoft's Json.net?
If your JSON needs are simple, you can reduce the size of your app ~1 MB by choosing Windows.Data.Json because it is part of the operating system.
I would recommend you try out Json.net nuget package and deserialise the json payload to classes through that.
A good tutorial can be found here: http://windowsapptutorials.com/windows-phone/general/deserialize-json-data-using-newtonsoft-json-net-library/
But if you search you'll find more.
In short, you first copy paste your json and use Visual Studio > File > Paste Special > To paste to classes ( first open an empty cs file and set your cursor inside it ).
After that you use JsonConvert.DeserializeObject<RootObject>() to actually parse the json string.
Once parsed you'll have an array of items if your original json also defined an array.
Note RootObject is the first class object in the generated classes in Visual Studio
There are ways to do it without external libraries, if that is the real reason for the stipulation of Windows.Data.Json.
I'd likely do it something like this...
First I'd make some classes representing the returning JSON:
public class RootObject
{
public Person person { get; set; }
}
public class Person
{
public string name { get; set; }
public string country { get; set; }
public string city { get; set; }
public string phone { get; set; }
}
Then add a little method to deserialize:
public static T Deserialize<T>(string json)
{
var bytes = Encoding.Unicode.GetBytes(json);
using (var ms = new MemoryStream(bytes))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
And finally deserialize and query that result like so:
var persons = Json.Deserialize<List<RootObject>>(textBox.Text);
var peeps = (from p in persons
where p.person.name.StartsWith("name")
select p).ToList();

Convert Json Unicode to Utf8

I'm facing a wierd problem when converting Json Unicode(?) to UTF8
"V\u00E4xj\u00F6" should be "Växjö"
Right now it seems like I've tried everything possible, but no luck.
Any coding ninjas out there that may sit on a solution? I'm sure it's fairly easy but still can't seem to figure it out.
Thank you
As Tomalak pointed out, it can be done using the System.Web.Helpers.Json.Decode method (no external libraries, .NET Framework). You need to build a simple JSON object to fetch the decoded text:
// helper class
public class Dummy
{
public String Field { get; set; }
}
//
var value = "V\u00E4xj\u00F6";
var sb = new StringBuilder();
sb.Append("{");
sb.Append(String.Format(#"""Field"" : ""{0}""", value));
sb.Append("}");
var dummy = Json.Decode(sb.ToString());
Console.WriteLine(dummy.Field);
// it works also without helper class
var obj = Json.Decode(sb.ToString());
Console.WriteLine(obj.Field);
The output is:
Växjö
Växjö
One possibility would be to use the Json.NET library to decode the string (or maybe for the whole JSON handling?). The deserializer decodes the string automatically. My test code looks like this:
// placeholder for the example
public class Sample
{
public String Name { get; set; }
}
//
var i = #"{ ""Name"" : ""V\u00E4xj\u00F6"" }";
var jsonConverter = Newtonsoft.Json.JsonConvert.DeserializeObject(i);
Console.WriteLine(jsonConverter.ToString());
//
var sample = Newtonsoft.Json.JsonConvert.DeserializeObject<Sample>(i);
Console.WriteLine(sample.Name);
The output is:
{
"Name": "Växjö"
}
Växjö

C# How to know which element is root object for deserialization?

I used json2csharp to get this:
http://pastebin.com/pbDYCrWk
From that, I wish to get the title that is held in the Oembed section.
I'm using this code:
string url = "http://www.reddit.com/r/all.json";
string jsonText = await DoStuff(url);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonText);
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Page.Oembed>(json);
string test = deserializeObject.title;
And I assumed it would work, however on the line with the deserializeObject variable, I get an error saying it can't do it.
I tried using Page.RootObject however it doesn't work either, and I assumed it would since it seems to be the root.
What am I doing wrong and how can I solve it? Thanks.
If you used Json2CSharp then it is RootObject:
public class RootObject
{
public string kind { get; set; }
public Data data { get; set; }
}
Should be:
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<JuicyReddit.RootObject>(json);

Parsing JSON data with javascriptserializer throws exception

I am getting JSON data in following format:
"[[\"NAME\",\"state\"],\n[\"Alabama\",\"01\"],\n[\"Alaska\",\"02\"]]"
I am trying to parse it with System.Web.Script.Serialization.JavaScriptSerializer the following way:
[Serializable]
private class State
{
private string Name { get; set; }
private string Code { get; set; }
}
private static List<State> getStates(string jsonData)
{
var json = new JavaScriptSerializer();
var parsedResult = json.Deserialize<List<State>>(jsonData);
return parsedResult;
}
The error I am getting is Type 'State' is not supported for deserialization of an array.
What am I doing wrong?Please suggest a way out.
Update
I have somewhat solved the problem since I need only a collection of the data in a queryable format. The following code did the trick:
var parsedResult = json.Deserialize<List<string[]>>(jsonData);
You have found workaround, nevertheless I think it's good to have explanation for the issue.
The problem you have is in brackets; [] means array, whereas object is market with {}. This means that to deserialize input string in array of State objects your input string should be formatted in following way:
[{\"NAME\",\"state\"},\n{\"Alabama\",\"01\"},\n{\"Alaska\",\"02\"}]

Deserializing JSON using C#

Finding some difficulty in sourcing information in trying to deserialize JSON in C#.
I have results from Google custom search returned in JSON format. I just want to check through my steps and establish the order in trying to deserialize it. Is this right?
I need to create classes to match
the JSON format. Kind of like a
creating schema file.
Use the JavaScriptSerializer() class and
deserialize method to extract the
relevant bits.
One of the issues I think I am going to run into is that I don't require all of the data returned but only the html links. How can I achieve that?
UPDATE
I have updated my question with the following JSON snippet and C# code. I want to output the string 'links' to console but it doesn't seem to be working. I think I am defining my classes wrongly?
JSON from Google Custom Search
handleResponse({
"kind": "customsearch#search",
"url": {
"type": "application/json",
"template": "https://www.googleapis.com/customsearch/v1?q\u003d{searchTerms}&num\u003d{count?}&start\u003d{startIndex?}&hr\u003d{language?}&safe\u003d{safe?}&cx\u003d{cx?}&cref\u003d{cref?}&sort\u003d{sort?}&alt\u003djson"
},
"queries": {
"nextPage": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 2,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
],
"request": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 1,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
]
},
"context": {
"title": "Curriculum",
"facets": [
[
{
"label": "lectures",
"anchor": "Lectures"
}
],
[
{
"label": "assignments",
"anchor": "Assignments"
}
],
[
{
"label": "reference",
"anchor": "Reference"
}
]
]
},
"items": [
{
"kind": "customsearch#result",
"title": "EE364a: Lecture Videos",
"htmlTitle": "EE364a: \u003cb\u003eLecture\u003c/b\u003e Videos",
"link": "http://www.stanford.edu/class/ee364a/videos.html",
"displayLink": "www.stanford.edu",
"snippet": "Apr 7, 2010 ... Course materials. Lecture slides · Lecture videos (2008) · Review sessions. Assignments. Homework · Reading. Exams. Final exam ...",
"htmlSnippet": "Apr 7, 2010 \u003cb\u003e...\u003c/b\u003e Course materials. \u003cb\u003eLecture\u003c/b\u003e slides · \u003cb\u003eLecture\u003c/b\u003e videos (2008) · Review sessions. \u003cbr\u003e Assignments. Homework · Reading. Exams. Final exam \u003cb\u003e...\u003c/b\u003e",
"cacheid": "TxVqFzFZLOsJ"
}
]
}
);
C# Snippet
public class GoogleSearchResults
{
public string link { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//input search term
Console.WriteLine("What is your search query?:");
string searchTerm = Console.ReadLine();
//concantenate the strings using + symbol to make it URL friendly for google
string searchTermFormat = searchTerm.Replace(" ", "+");
//create a new instance of Webclient and use DownloadString method from the Webclient class to extract download html
WebClient client = new WebClient();
string Json = client.DownloadString("https://www.googleapis.com/customsearch/v1?key=My Key&cx=My CX&q=" + searchTermFormat);
//create a new instance of JavaScriptSerializer and deserialise the desired content
JavaScriptSerializer js = new JavaScriptSerializer();
GoogleSearchResults results = js.Deserialize<GoogleSearchResults>(Json);
Console.WriteLine(results);
//Console.WriteLine(htmlDoc);
Console.ReadLine();
}
}
Thanks
I use your #2 approach: deserialize with the JavaScriptSerializer.
This is what I do to deserialize a response from Facebook:
// get the id for the uploaded photo
var jss = new JavaScriptSerializer();
var resource = jss.Deserialize<Facebook.Data.Resource>(responseText);
....where Facebook.Data.Resource is defined like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
}
The responseText that I am deserializing from looks like this:
{"id":"10150111918987952",
"from":{"name":"Someone",
"id":"782272221"},
"name":"uploaded from Cropper. (at 12\/15\/2010 7:06:41 AM)",
"picture":"http:\/\/photos-f.ak.fbcdn.net\/hphotos-ak-snc4\/hs817.snc4\/69790_101501113333332_782377951_7551951_8193638_s.jpg",
...
But since I have only one property defined in the Resource class, I only deserialize that. Define the fields in your class that you want to deserialize.
It works to use inheritance, of course. You can define your data classes like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
public class Person : Resource
{
public string name { get; set; }
}
}
...and then you can deserialize a Person object.
EDIT
Ok, given the sample json you provided in the updated question, here's how I wrote the classes to hold the response:
public class GoogleSearchItem
{
public string kind { get; set; }
public string title { get; set; }
public string link { get; set; }
public string displayLink { get; set; }
// and so on... add more properties here if you want
// to deserialize them
}
public class SourceUrl
{
public string type { get; set; }
public string template { get; set; }
}
public class GoogleSearchResults
{
public string kind { get; set; }
public SourceUrl url { get; set; }
public GoogleSearchItem[] items { get; set; }
// and so on... add more properties here if you want to
// deserialize them
}
And here's the C# code to deserialize:
// create a new instance of JavaScriptSerializer
JavaScriptSerializer s1 = new JavaScriptSerializer();
// deserialise the received response
GoogleSearchResults results = s1.Deserialize<GoogleSearchResults>(json);
Console.WriteLine(s1.Serialize(results));
Some comments:
The toplevel class to hold the search result is called GoogleSearchResults.
The first property in the GoogleSearchResults class is kind, corresponding to the first named property in the json object. You had link which isn't going to work, because link is not the name of a top-level property in that json object. There are properties lower in the hierarchy of your json named "link" but JavaScriptSerializer won't pull out those lower level things into the higher level.
The next property in my GoogleSearchResults class is of type SourceUrl. This is because the url property in the json is not a simple string - it is a json object with two properties, each with a string value. So SourceUrl as a class in C# gets two string properties, each with the appropriate name to deserialize one of those named properties.
the next property in the GoogleSearchResults class is called "items" so that it can deserialize the items dictionary from your json. Now items, as the name suggests, is an array in the json, as denoted by the square bracket around its value. This means there can be more than one item, although in your case there is just one item. So this property in C# must be an array (or collection). Each item in the json result is not a simple string, so, once again, as we did with SourceUrl, we need to define a holder class to deserialize the item object: GoogleSearchItem. This class has a bunch of simple string properties. The properties in the C# class could also be of type int or some other type, if that's what the json requires.
finally, when printing out the result, if you just call Console.WriteLine(result) you will see the result of the ToString() method that is implicitly invoked by Console.WriteLine. This will merely print the name of the type, in this case is "GoogleSearchResults", which is not what you want, I think. In order to see what's in the object, you need to serialize it, as I've shown. In the output of that, you will see only the values of things you deserialized. Using the classes I provided, the result will have less information than the original, because I didn't provide properties in the C# class corresponding to some of the json properties, so those weren't deserialized.
You could take a look at Json.NET and its LINQ support to create and query JSON. By crafting a nice LINQ query you will get only the stuff you need (you can select, group by, count, min, max, whatever you like).
http://msdn.microsoft.com/en-us/library/bb412170.aspx
http://msdn.microsoft.com/en-us/library/bb410770.aspx
Pull out the property you need after you have converted the JSON representation to a type in your C# app. I don't think there's a way to extract only one property from the JSON representation before you have converted it (though I am not sure).

Categories

Resources