C# Non-standard JSON parsing - c#

I have an oddly formulated JSON response string in this format:
{
"Result": <this is the array of Ticket objects>,
"IsLastPage": true,
"NextSkip": 1,
"NextTake": 1,
"PageCount": 2,
"TotalCount": 3,
"QueryResultHash": "sample string 4"
}
Usually I would access the Json array (the Result value above) when the array is the only thing being returned, like so:
var jsonArray = JArray.Parse(resultString);
foreach (var jsonObject in jsonArray)
{ ... }
But I am not sure how to break down the above string so that I can get the 7 values individually and parse the array. Any suggestions?

If possible, I would use the library Newtonsoft.Json (https://www.nuget.org/packages/Newtonsoft.Json/).
Then you can create a ResponseContainer class. Something like,
//generated by http://json2csharp.com/
public class ResponseContainer
{
public List<object> Result { get; set; }
public bool IsLastPage { get; set; }
public int NextSkip { get; set; }
public int NextTake { get; set; }
public int PageCount { get; set; }
public int TotalCount { get; set; }
public string QueryResultHash { get; set; }
}
Then you can do
JsonSerializer serializer = new JsonSerializer();
ResponseContainer response = serializer.Deserialize<ResponseContainer>(jsonString);
Now you can access the fields in the json response as a C# object.

Related

Get multiples Arrays from dictionary Object

I have a JSON call, this brings me an object with four Arrays.
HttpWebRequest apiRequest = WebRequest.Create(url) as HttpWebRequest;
string apiResponse = "";
using (HttpWebResponse response = apiRequest.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
apiResponse = reader.ReadToEnd();
}
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(apiResponse);
var results = dict["results"];
Then i use var dict to storage this four arrays, later i have var results to select an specific array. In this case, the array i want is "results".
var results "output":
The problem is i want access the data for each array, but i don't know how do this.
ArrayList list = (ArrayList)results;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < list.Count; i++)
{
if (builder.Length > 0)
{
builder.Append(", ");
}
object current = list[i];
builder.Append(current);
}
LblTitle.Text = builder.ToString();
I see this code in other post and i adapt to my code, but this only brings me this System.Collections.Generic.Dictionary'2[System.String,System.Object], for each array.
I want something like this
string[] arrayresult = builder.ToString();
string[] arrayresult2 = builder.ToString();
etc, for each array in the object results. And later access each array data like this LblTitle.Text = arrayresult[1]; LblTitle2.Text = arrayresult2[1];
Edit: Adding JSON Example
"{\"page\":1,\"results\":[{\"adult\":false,\"backdrop_path\":\"/7ABsaBkO1jA2psC8Hy4IDhkID4h.jpg\",\"genre_ids\":[28,12,14,878],\"id\":19995,\"original_language\":\"en\",\"original_title\":\"Avatar\",\"overview\":\"In the 22nd century, a paraplegic Marine is dispatched to the moon Pandora on a unique mission, but becomes torn between following orders and protecting an alien civilization.\",\"popularity\":1363.938,\"poster_path\":\"/jRXYjXNq0Cs2TcJjLkki24MLp7u.jpg\",\"release_date\":\"2009-12-10\",\"title\":\"Avatar\",\"video\":false,\"vote_average\":7.5,\"vote_count\":26216},{\"adult\":false,\"backdrop_path\":\"/198vrF8k7mfQ4FjDJsBmdQcaiyq.jpg\",\"genre_ids\":[878,28,12],\"id\":76600,\"original_language\":\"en\",\"original_title\":\"Avatar: The Way of Water\",\"overview\":\"Set more than a decade after the events of the first film, learn the story of the Sully family (Jake, Neytiri, and their kids), the trouble that follows them, the lengths they go to keep each other safe, the battles they fight to stay alive, and the tragedies they endure.\",\"popularity\":1000.602,\"poster_path\":\"/1yppMeTNQwDrzaUH4dRCx4mr8We.jpg\",\"release_date\":\"2022-12-14\",\"title\":\"Avatar: The Way of Water\",\"video\":false,\"vote_average\":0,\"vote_count\":0},{\"adult\":false,\"backdrop_path\":null,\"genre_ids\":[99],\"id\":287003,\"original_language\":\"en\",\"original_title\":\"Avatar: Scene Deconstruction\",\"overview\":\"The deconstruction of the Avatar scenes and sets\",\"popularity\":261.979,\"poster_path\":\"/uCreCQFReeF0RiIXkQypRYHwikx.jpg\",\"release_date\":\"2009-12-18\",\"title\":\"Avatar: Scene Deconstruction\",\"video\":false,\"vote_average\":9,\"vote_count\":3},{\"adult\":false,\"backdrop_path\":null,\"genre_ids\":[99],\"id\":111332,\"original_language\":\"en\",\"original_title\":\"Avatar: Creating the World of Pandora\",\"overview\":\"The Making-of James Cameron's Avatar. It shows interesting parts of the work on the set.\",\"popularity\":259.613,\"poster_path\":\"/d9oqcfeCyc3zmMal6eJbfj3gatc.jpg\",\"release_date\":\"2010-02-07\",\"title\":\"Avatar: Creating the World of Pandora\",\"video\":false,\"vote_average\":7,\"vote_count\":20}],\"total_pages\":3,\"total_results\":55}"
I convert this JSON to Class, thanks for the tip. This is my class now:
public class Result
{
public bool adult { get; set; }
public string backdrop_path { get; set; }
public List<int> genre_ids { get; set; }
public int id { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public string overview { get; set; }
public double popularity { get; set; }
public string poster_path { get; set; }
public string release_date { get; set; }
public string title { get; set; }
public bool video { get; set; }
public double vote_average { get; set; }
public int vote_count { get; set; }
}
public class Root
{
public int page { get; set; }
public List<Result> results { get; set; }
public int total_pages { get; set; }
public int total_results { get; set; }
}
I would suggest you create a proper C# class to deserialize your JSON into. We can't see how you JSON looks, so I'll just give a simple example. Let's say this is your JSON:
{
"results": [
[
"foo",
"bar"
],
[
"baz",
"qux"
]
],
"someOtherField": "someValue"
}
If you go to https://json2csharp.com/ you can convert this into a C# class like this:
public class Root
{
public List<List<string>> results { get; set; }
public string someOtherField { get; set; }
}
To deserialize and access the data, you simply do the following (I'm using System.Text.Json instead of JavaScriptSerializer - see comment below):
var root = JsonSerializer.Deserialize<Root>(apiResponse);
// ...
List<string> listResult = root.results[0];
List<string> listResult2 = root.results[1];
// ...
LblTitle.Text = listResult[1]; // "bar"
LblTitle2.Text = listResult2[1]; // "qux"
Please refer to the definition of JavaScriptSerializer:
For .NET Framework 4.7.2 and later versions, use the APIs in the System.Text.Json namespace for serialization and deserialization. For earlier versions of .NET Framework, use Newtonsoft.Json.
See here for how to use System.Text.Json .
If you want to use Newtonsoft.Json instead, you should replace JsonSerializer.Deserialize with JsonConvert.DeserializeObject:
var root = JsonConvert.DeserializeObject<Root>(apiResponse);

Read JSON Array that contains Arrays(?) C#

I apologize in advance for the poor explanation of my problem.
I'm trying to read a JSON array that contains data.
Here's how the JSON looks:
{
"playerstats": {
"steamID": "76561198071680006",
"gameName": "GameName",
"achievements": [
{
"apiname": "AchievementName1",
"achieved": 0, <--- Data that I want to read
"unlocktime": 0
},
{
"apiname": "AchievementName2",
"achieved": 0, <--- Data that I want to read
"unlocktime": 0
},
{
"apiname": "AchievementName2",
"achieved": 1, <--- Data that I want to read
"unlocktime": 1477847680
}
]
,
"success": true
}
}
I'm trying to look at Newtonsoft.Json and how to use that yet I'm at a complete loss as to how to use this. Any help would be appreciated.
You can try JsonConvert.DeserializeObject to read json data.
Having
public class Rootobject
{
public Playerstats playerstats { get; set; }
}
public class Playerstats
{
public string steamID { get; set; }
public string gameName { get; set; }
public Achievement[] achievements { get; set; }
public bool success { get; set; }
}
public class Achievement
{
public string apiname { get; set; }
public int achieved { get; set; }
public int unlocktime { get; set; }
}
You can try this:
var filePath = path to your file;
var jsonData = System.IO.File.ReadAllText(filePath);
Rootobject objectValue =
Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(jsonData);
Note: you should remove <--- Data that I want to read parts from your json data because currently it is not a valid json format.
You may access to your desired properties like this
objectValue.playerstats.achievements[0].achieved //0
objectValue.playerstats.achievements[1].achieved //0
objectValue.playerstats.achievements[2].achieved //1

Parse data from multiple json arrays in c#

I am trying to search this Json Code to find statistics:
{
"summonerId": 32033681,
"modifyDate": 1403658807000,
"champions": [{
"id": 40,
"stats": {
"totalSessionsPlayed": 1,
"totalSessionsLost": 0,
"totalSessionsWon": 1,
"totalChampionKills": 1,
"totalDamageDealt": 27006,
"totalDamageTaken": 9924,
"mostChampionKillsPerSession": 1,
"totalMinionKills": 17,
"totalDoubleKills": 0,
"totalTripleKills": 0,
"totalQuadraKills": 0,
"totalPentaKills": 0,
"totalUnrealKills": 0,
"totalDeathsPerSession": 2,
"totalGoldEarned": 8383,
"mostSpellsCast": 0,
"totalTurretsKilled": 2,
"totalPhysicalDamageDealt": 8957,
"totalMagicDamageDealt": 18049,
"totalFirstBlood": 0,
"totalAssists": 13,
"maxChampionsKilled": 1,
"maxNumDeaths": 2
}
},
{
"id": 36,
"stats": {
"totalSessionsPlayed": 1,
"totalSessionsLost": 1,
"totalSessionsWon": 0,
"totalChampionKills": 0,
"totalDamageDealt": 14267,
"totalDamageTaken": 7649,
"mostChampionKillsPerSession": 0,
"totalMinionKills": 33,
"totalDoubleKills": 0,
"totalTripleKills": 0,
"totalQuadraKills": 0,
"totalPentaKills": 0,
"totalUnrealKills": 0,
"totalDeathsPerSession": 5,
"totalGoldEarned": 3258,
"mostSpellsCast": 0,
"totalTurretsKilled": 0,
"totalPhysicalDamageDealt": 4992,
"totalMagicDamageDealt": 9165,
"totalFirstBlood": 0,
"totalAssists": 0,
"maxChampionsKilled": 0,
"maxNumDeaths": 5
}
}]
}
In the following example, I want to be able search for totalSessionsWon for id 36. I tried accessing the data how I have been accessing data from other JSON files but it doesn't allow me to specify the id of the champion I am searching for:
string jsonInput = new WebClient().DownloadString(#usableurl); //Reads the JSON from the API
string usableJson = #"JObject.Parse(jsonInput)"; //converts the JSON from the API to a usable form
var usableJson["champions"]["stats"]["totalSessionWon"];
Is there a way that I could choose a specific statistic based on the id before it?
I'm new to using both JSON and C#, so your help is especially appreciated!
If Newtonsoft.Json; is new for you than you can have a look at how to install Newtonsoft now once the installation is done i would love to tell you that XML, JSON are an open-standard format that uses human-readable text to transmit data objects consisting of attribute–value pairs. The fetching of the data from this kind of strings would be as easier as database.
For fetching the data from the json string with ease first we need to make the object of the json string which shows the heirarchy and thus we need to see how our data or json string looks like. So if you see the top most level of the heirarchy contains summonerId, modifyDate and champions Inside champions there could be n number of champion details so we created the list of champion as champions
now one level down of the heirarchy you can see the champion id and his stats so stats would be one more class to create about the champion. so your class would look like
public class Rootobject
{
public int summonerId { get; set; }
public long modifyDate { get; set; }
public List<Champion> champions { get; set; }
}
public class Champion
{
public int id { get; set; }
public Stats stats { get; set; }
}
public class Stats
{
public int totalSessionsPlayed { get; set; }
public int totalSessionsLost { get; set; }
public int totalSessionsWon { get; set; }
public int totalChampionKills { get; set; }
public int totalDamageDealt { get; set; }
public int totalDamageTaken { get; set; }
public int mostChampionKillsPerSession { get; set; }
public int totalMinionKills { get; set; }
public int totalDoubleKills { get; set; }
public int totalTripleKills { get; set; }
public int totalQuadraKills { get; set; }
public int totalPentaKills { get; set; }
public int totalUnrealKills { get; set; }
public int totalDeathsPerSession { get; set; }
public int totalGoldEarned { get; set; }
public int mostSpellsCast { get; set; }
public int totalTurretsKilled { get; set; }
public int totalPhysicalDamageDealt { get; set; }
public int totalMagicDamageDealt { get; set; }
public int totalFirstBlood { get; set; }
public int totalAssists { get; set; }
public int maxChampionsKilled { get; set; }
public int maxNumDeaths { get; set; }
}
Now since we already got the structure we need to Deserialize the string to the object of our type that is Rootobject. That will convert that normal json string to fill in the objects. Now just fetch the details like eating a cake.
using Newtonsoft.Json;
Rootobject rt = JsonConvert.DeserializeObject<Rootobject>(jsonstr);
if(rt.champions[1].id == 36)
{
Console.WriteLine(rt.champions[1].stats.totalSessionsWon);
}
As the question's author was attempting to use JObject to query their JSON object, I thought I would give a solution using the same.
JObject is for querying JSON with Linq. Linq is a semi-advanced subject for new C# programmers to get their head around but in short, is a specialised query language for retrieving data from a data source. The method outlined in Mohit Shrivastrava's answer is much easier for new programmers to get their head around.
//converts the JSON from the API to a usable form
JObject usableJson = JObject.Parse(json);
// retrieve champion objects
JToken champions = usableJson["champions"];
// retrieve the champion desired object using the Linq FirstOrDefault method.
// This method will return the first object that matches the given query,
// or return null if it does not find a match.
JToken champion = champions.FirstOrDefault(c=> (int)c["id"] == 36);
if (champion != null)
{
// retrieve the stats object
JToken stats = champion["stats"];
// read the totalSessionsWon field from the object.
int totalSessionsWon = (int) stats["totalSessionsWon"];
}

Getting an exception when trying to deserialize JSON and display the results in a DataGridView

I have some C# code where I get JSON data from an API. The JSON looks like this:
{
"count": 32696,
"results": [{
"data_id": 0,
"name": "Extended Potion of Ghost Slaying",
"rarity": 0,
"restriction_level": 0,
"img": "",
"type_id": 0,
"sub_type_id": 0,
"price_last_changed": "2013-03-18 17:00:31 UTC",
"max_offer_unit_price": 0,
"min_sale_unit_price": 0,
"offer_availability": 0,
"sale_availability": 0,
"sale_price_change_last_hour": 0,
"offer_price_change_last_hour": 0
}]
}
(There is more than just one item in the results though.)
I have made 2 classes like this:
internal class MyClass
{
public int data_id { get; set; }
public string name { get; set; }
public int rarity { get; set; }
public int restriction_level { get; set; }
public string img { get; set; }
public int type_id { get; set; }
public int sub_type_id { get; set; }
public string price_last_changed { get; set; }
public int max_offer_unit_price { get; set; }
public int min_sale_unit_price { get; set; }
public int offer_availability { get; set; }
public int sale_availability { get; set; }
public int sale_price_change_last_hour { get; set; }
public int offer_price_change_last_hour { get; set; }
}
internal class RootObject
{
public int count { get; set; }
public List<MyClass> results { get; set; }
}
And here is the part where I get the JSON and deserialize it:
using (WebClient wc = new WebClient())
{
string URI = "a good url";
wc.Headers.Add("Content-Type", "text");
string HtmlResult = wc.DownloadString(URI);
MyClass[] result = JsonConvert.DeserializeObject<MyClass[]>(HtmlResult);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(HtmlResult, (typeof(DataTable)));
this.dataGridView1.DataSource = dt;
}
But when I run this code I get an error:
Additional information: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type 'gwspiderv2.MyClass[]' because the
type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
I already use this type of code on another API without errors. What am I doing wrong?
In your code it seems you are trying to deserialize the same JSON two different ways, which doesn't make a whole lot of sense:
MyClass[] result = JsonConvert.DeserializeObject<MyClass[]>(HtmlResult);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(HtmlResult, (typeof(DataTable)));
You are getting the first error (in your question) because your JSON represents a single object, but you are trying to deserialize it into an array of MyClass. You have defined a RootObject class, but you are not using it. It seems that you should be, because it fits your JSON.
You are getting the second error (in the comments to #inan's answer) because the JSON is in the wrong format to be deserialized into a DataTable. Presumably you are trying to do that so you can display the data in your DataGridView. But you don't need to convert it to a DataTable in order to use it as a data source. You can just give your DataGridView an IList, which you already have in your RootObject.
Change your code to this:
RootObject result = JsonConvert.DeserializeObject<RootObject>(HtmlResult);
this.dataGridView1.DataSource = result.results;
Use RootObject for deserializing as below, it has the List of MyClass
RootObject result = JsonConvert.DeserializeObject<RootObject>(HtmlResult);

Store a JSON string in C# and then access individual parts of it

I am pulling some JSON from an API. It comes in this format:
{"yourname": {
"id": 42728521,
"name": "Your Name",
"profileIconId": 27,
"revisionDate": 1397930999000,
"summonerLevel": 1
}}
However, that is stored as:
"{\"yourname\":{\"id\":42728521,\"name\":\"Your Name\",\"profileIconId\":27,\"summonerLevel\":1,\"revisionDate\":1397930999000}}"
Inside the string.
I want to be able to call summonerLevel and for it to return the correct value.
I've been trying this:
using (var client = new WebClient())
{
api_return = client.DownloadString(api_call_key);
}
var foo = JsonConvert.DeserializeObject<Summoner>(api_return);
Console.WriteLine(Summoner.id);
Console.WriteLine(Summoner.name);
Console.WriteLine(Summoner.summonerLevel);
string id_ = foo.ToString();
Console.WriteLine(id_);
Console.ReadKey();
}
public class Summoner
{
public static int id { get; set; }
public static string name { get; set; }
public static int summonerLevel { get; set; }
}
However, that just prints out:
0
nothing
0
You have two issues here, which are both preventing you from getting the data from the JSON.
The first issue is that the properties of your Summoner class should not be static, as Vikas pointed out. Define your class like this:
public class Summoner
{
public int id { get; set; }
public string name { get; set; }
public int summonerLevel { get; set; }
}
The second issue is that your JSON structure doesn't match what you're deserializing into. The id, name and summonerLevel properties are not at the root level of the JSON, they are one level further down, inside another object. So, you'll need to deserialize into some class that "wraps" your Summoner. If the yourname property in the JSON were a fixed value, you could define a Wrapper class like this to deserialize into:
public class Wrapper
{
[JsonProperty("yourname")]
public Summoner Summoner { get; set; }
}
However, since the yourname property in the JSON is likely not a fixed value (it could change for different summoners), I would recommend deserializing into a Dictionary<string, Summoner> like this instead:
var dict = JsonConvert.DeserializeObject<Dictionary<string, Summoner>>(json);
From there, you can either loop through the dictionary key-value pairs, or, if you're only expecting one, you can use First() to get it.
var summoner = dict.First().Value;
Here is a full demo:
string json = #"{""yourname"": {
""id"": 42728521,
""name"": ""Your Name"",
""profileIconId"": 27,
""revisionDate"": 1397930999000,
""summonerLevel"": 1
}}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, Summoner>>(json);
var summoner = dict.First().Value;
Console.WriteLine(summoner.id);
Console.WriteLine(summoner.name);
Console.WriteLine(summoner.summonerLevel);
Output:
42728521
Your Name
1
Properties in Summoner class should not be static
using (var client = new WebClient())
{
api_return = client.DownloadString(api_call_key);
}
var foo = JsonConvert.DeserializeObject<Summoner>(api_return);
Console.WriteLine(foo.id);
Console.WriteLine(foo.name);
Console.WriteLine(foo.summonerLevel);
..............
}
public class Summoner
{
public int id { get; set; }
public string name { get; set; }
public int summonerLevel { get; set; }
}

Categories

Resources