How do I read specific sections of a large JSON string? - c#

I make a call to the Riot Games API https://developer.riotgames.com/
It returns this huge output (link to pastebin) in JSON.
The JSON contains 6 "Participants" and I want to create 6 participant objects from the output. My problem is that there are other sections than the "Participants" such as "gameid", "gamestarttime" and etc. Because of this I don't know how to read out only the JSON text under the "participants:" section.
In short, how do I get single out only the data under "participants" or how do I create only objects from the "participants" section of the output?
Here is my code that would work if there wasn't anything other than participants:
// Create a string containing the output from the API call
var jsonString = GetResponse("https://euw1.api.riotgames.com/lol/spectator/v3/active-games/by-summoner/79200188?api_key=xxxxxxxxxxxxxxxxxxxxxxxxxx");
// Create a list of Participants containing the data from the JSON
var participantsList = JsonConvert.DeserializeObject<List<Participant>>(jsonString);
// Show the names of the participants
foreach (var item in participantsList)
{
MessageBox.Show(item.summonerName);
}
Here is my Participant class which from which I want to create objects from the JSON.
class Participant
{
public int profileIconId { get; set; }
public int championId { get; set; }
public string summonerName { get; set; }
public bool bot { get; set; }
public int spell2Id { get; set; }
public int teamId { get; set; }
public int spell1Id { get; set; }
public int summonerId { get; set; }
}

As per my comment, json.net only deserializes the fields that it can find in the model. So just put only the fields you want to take from the json in the model.
Example POCO's:
public class GameData {
public string gameId {get; set;}
public int mapId {get; set;} //just demonstrating that it only fills in the fields you put in the model
public List<Participant> participants = new List<Participant>();
}
...
public class Participant
{
public int profileIconId { get; set; }
public int championId { get; set; }
public string summonerName { get; set; }
public bool bot { get; set; }
public int spell2Id { get; set; }
public int teamId { get; set; }
public int spell1Id { get; set; }
public int summonerId { get; set; }
}
Deserialize like so:
var gameInfo = JsonConvert.DeserializeObject<GameData>(jsonString);
var participantsList = gameInfo.participants;

If you have no problem in creating one more model then create a Base Model
public class GameData
{
public string gameId {get; set;}
public int mapId {get; set;}
public List<Participant> participants
}
and use
var gameData =JsonConvert.DeserializeObject<GameData>(jsonString);
If you do not want to create one more model the you can convert the jsonString to Jobject then extract out sing values or deserialize from that value
For eg,
var jsonString = GetResponse("https://euw1.api.riotgames.com/lol/spectator/v3/active-games/by-summoner/79200188?api_key=RGAPI-dc7c328a-dd2b-40ca-8ccd-71d05d530a4e");
JObject json = JObject.Parse(jsonString);
var gameId = json .GetValue("filetype").ToString();
You can do this to extract other values too

Related

Deserializing Json to Entity Framework cant convert int to type

I've been trying to deserialize a Json string that contains a list of ints representing colors to then be inserted into a sql database using Entity Framework. I'm pretty new to Entity Framework and read that it doesn't support collections of primitive types, I thought to get around it I could add the class
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
and then create a list in the CharacterColor class to hold the ints
public List<Colors> Colors { get; set; }
However I get the error when trying to deserialize the Json.
Newtonsoft.Json.JsonSerializationException: 'Error converting value
255 to type 'ORAC.Data.Entities.Colors'. Path
'characterColors[0].colors[0]', line 1, position 1200.'
ArgumentException: Could not cast or convert from System.Int64 to ORAC.Data.Entities.Colors.
Would anyone with more experience with Entity Framework be able to see where I'm going wrong.
Character character = JsonConvert.DeserializeObject<Character>(jsonString);
Json string
"{\"packedRecipeType\":\"DynamicCharacterAvatar\",\"name\":\"Character\",\"race\":\"HumanMaleHighPoly\",\"dna\":[{\"dnaType\":\"UMADnaHumanoid\",\"dnaTypeHash\":-212795365,\"packedDna\":\"{\\\"height\\\":128,\\\"headSize\\\":128,\\\"headWidth\\\":93,\\\"neckThickness\\\":108,\\\"armLength\\\":135,\\\"forearmLength\\\":128,\\\"armWidth\\\":116,\\\"forearmWidth\\\":128,\\\"handsSize\\\":118,\\\"feetSize\\\":109,\\\"legSeparation\\\":128,\\\"upperMuscle\\\":129,\\\"lowerMuscle\\\":152,\\\"upperWeight\\\":128,\\\"lowerWeight\\\":81,\\\"legsSize\\\":134,\\\"belly\\\":66,\\\"waist\\\":108,\\\"gluteusSize\\\":38,\\\"earsSize\\\":121,\\\"earsPosition\\\":233,\\\"earsRotation\\\":61,\\\"noseSize\\\":115,\\\"noseCurve\\\":128,\\\"noseWidth\\\":124,\\\"noseInclination\\\":128,\\\"nosePosition\\\":128,\\\"nosePronounced\\\":128,\\\"noseFlatten\\\":118,\\\"chinSize\\\":128,\\\"chinPronounced\\\":128,\\\"chinPosition\\\":128,\\\"mandibleSize\\\":128,\\\"jawsSize\\\":128,\\\"jawsPosition\\\":128,\\\"cheekSize\\\":128,\\\"cheekPosition\\\":128,\\\"lowCheekPronounced\\\":128,\\\"lowCheekPosition\\\":195,\\\"foreheadSize\\\":128,\\\"foreheadPosition\\\":128,\\\"lipsSize\\\":128,\\\"mouthSize\\\":128,\\\"eyeRotation\\\":128,\\\"eyeSize\\\":69,\\\"breastSize\\\":128}\"},{\"dnaType\":\"UMADnaTutorial\",\"dnaTypeHash\":-1679007774,\"packedDna\":\"{\\\"eyeSpacing\\\":128}\"}],\"characterColors\":[{\"name\":\"Skin\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Hair\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Eyes\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Undies\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]}],\"wardrobeSet\":[{\"slot\":\"Underwear\",\"recipe\":\"MaleUnderwear\"}],\"raceAnimatorController\":\"Locomotion\"}"
Entity
public class Character
{
public int UserId { get; set; }
public int CharacterId { get; set; }
public string CharacterName { get; set; }
public string PackedRecipeType { get; set; }
public string Name { get; set; }
public string Race { get; set; }
public List<Dna> Dna { get; set; }
public List<CharacterColor> CharacterColors { get; set; }
public List<WardrobeSet> WardrobeSet { get; set; }
public string RaceAnimatorController { get; set; }
public User User { get; set; }
}
public class Dna
{
public int Id { get; set; }
public string DnaType { get; set; }
public int DnaTypeHash { get; set; }
public string PackedDna { get; set; }
}
public class CharacterColor
{
public int Id { get; set; }
public string Name { get; set; }
public List<Colors> Colors { get; set; }
}
public class WardrobeSet
{
public int Id { get; set; }
public string Slot { get; set; }
public string Recipe { get; set; }
}
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
Solution
I updated the Json and replaced the colors array with a new array of objects
JObject jsonToParse = JObject.Parse(jsonString);
JArray characterColors = (JArray)jsonToParse["characterColors"];
foreach(var item in characterColors)
{
JArray colors = (JArray)item["colors"];
JArray newColorsArray = new JArray();
var i = 0;
foreach (var col in colors)
{
var color = new Color
{
ColorId = i,
Value = (int)col
};
newColorsArray.Add(JToken.FromObject(color));
i++;
}
colors.Replace(newColorsArray);
}
In your Json you have colors defined as an array of ints, not as an object array of your new Colors class. Should be more like colors: [{Id:0, Color:255},{Id:2, Color:255}, .......]
So the JSON is incorrect, in the json the colors array is sent as a List basically
colors: [255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]
but the .net is expecting something more like the following which is more like a List
colors: [{Id:0, Color:255},{Id:1, Color:255}, ...]
So you can do any of the following:
Change whatever is sending your JSON to send an array of objects of {int, int} instead of an array of ints.
Change your List to be a List and then update all your .net code to adjust to that.
Write a custom Json converter to convert from the json you have to the .net that you have.
You should do 1 or 2, as your data doesn't seem complex enough to go through the effort of 3.

Deserialize Object into a class does not work

I am trying to set a class for a token using DeserializeObject from the json object i get back from my api. However when i run the below code it sets all the values to null or 0, not the result i am getting from the api.
cs code
var resultString = await result.Content.ReadAsStringAsync();
var post = JsonConvert.DeserializeObject<Token>(resultString);
class
public class Token : ContentPage
{
public int StaffID { get; set; }
public string TokenApi { get; set; }
public string StaffForename { get; set; }
public string StaffSurname { get; set; }
public string StaffEmail { get; set; }
public int PrimaryStaffRoleID { get; set; }
}
JSON response
"{\"code\":201,\"status\":\"Success\",\"message\":\"Object found\",\"data\":{\"StaffID\":14,\"StaffSurname\":\"Test\",\"StaffForename\":\"Test\",\"StaffEmail\":\"test#test.com\",\"PrimaryStaffRoleID\":5,\"TokenApi\":\"testToken\"}}"
Firstly the data which you are trying to map is inside another property in your json called Data and secondly your json does not have a property with name Token
The problem actually is you are not using the correct type that reflects your json, means you don't have correct c# type which would get mapped to json, you can generate correct types using json2charp.com , the correct classes for it are :
public class Data
{
public int StaffID { get; set; }
public string StaffSurname { get; set; }
public string StaffForename { get; set; }
public string StaffEmail { get; set; }
public int PrimaryStaffRoleID { get; set; }
public string TokenApi { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string status { get; set; }
public string message { get; set; }
public Data data { get; set; }
}
Now deserializing using RootObject as type parameter would work perfectly fine like:
var resultString = await result.Content.ReadAsStringAsync();
var post = JsonConvert.DeserializeObject<RootObject>(resultString);
A more good option is to use QuickType.IO which would even generate code for you in c# or any other language that they are supporting.
If you analyze the JSON that you posted, the object that you're trying to Deserialize is inside the "data" property of your json.
I suggest you creating a class to represent the JsonResponse with a Data property. This will be your Token
You are retrieved a string that match this object
public string code {get;set;}
public string Success {get;set;} ...
And Token is matching data in json, so
var post = JsonConvert.DeserializeObject<Token>(resultString.data);
would be better.

Deserializing complex JSON using C#

public class Rootobject
{
public EnPickthall enpickthall { get; set; }
}
public class EnPickthall
{
public _1 _1 { get; set; }
public _2 _2 { get; set; }
public _3 _3 { get; set; }
public _4 _4 { get; set; }
/* This goes on*/
public _6236 _6236 { get; set;}
}
//For Each of the above properties a separate class has been defined:
public class _1
{
public int id { get; set; }
public int surah { get; set; }
public int ayah { get; set; }
public string verse { get; set; }
}
public class _2
{
public int id { get; set; }
public int surah { get; set; }
public int ayah { get; set; }
public string verse { get; set; }
}
/* So On for all the properties */
I got this via JSON2CSHARP!
My problem is if I employ so many properties retrieving all Verses based upon their "Surah" would be very difficult & Impractical
Here I have a book in EnPickthall class which has a separate Class for every verse. Every Verse here has it's own class.
I have been scavenging Stack Overflow for hours.Is there any way I could simplify this JSON Classes.
My Code to Creating the object model :
var serializer = new DataContractJsonSerializer(typeof(RootObject_Quran));
var result= App_Code.FileIOHelper.ReadFromDefaultFile("ms-appx:///Assets/en.pickthall.json");
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_Quran)serializer.ReadObject(ms);
My JSON File Link : http://globalquran.com/download/data/download.php?data_by=json&quran_by_id[]=en.pickthall
Just have a single class called Verse.
public class Verse {
public int SurahId { get; set; }
public int AyaId { get; set; }
public String Text { get; set; }
}
You don't really need a key for each verse, as the surah/aya combination is sufficient to uniquely identify a verse.
This allows for easy serialization/deserialization and also allows for easy gathering into the entire Quran again, by ordering on Surah and Aya. You could then simply use LINQ to reassemble the entire book, ordered as state above. Or it would be incredibly simple to gather passages from it also, based on a search criteria e.g. 27:18-20
Json is nested with property en.pickthall than all data wrapper again into property like id numbers so i made class and that class has Dictionary to handle data and numbers
[JsonProperty(PropertyName = "en.pickthall")]
public Dictionary picthall {get;set;}
public class VerseObject
{
[JsonProperty(PropertyName = "en.pickthall")]
public Dictionary<int, Data> picthall {get;set;}
}
public class Data
{
[JsonProperty(PropertyName = "id")]
public int id;
[JsonProperty(PropertyName = "surah")]
public int surah;
[JsonProperty(PropertyName = "ayah")]
public int ayah;
[JsonProperty(PropertyName = "verse")]
public string verse;
}
class Program
{
static void Main(string[] args)
{
List<Data> v = new List<Data>();
using (StreamReader rdr = new StreamReader(#"C:\Temp\en.pickthall.json"))
{
var str = rdr.ReadToEnd();
var jsn = JsonConvert.DeserializeObject<VerseObject>(str);
foreach(var item in jsn.picthall.Select(x=>x.Value))
{
v.Add(item);
}
Console.ReadLine();
}
}
}

How do I deserialize a JSON array using Newtonsoft.Json

[
{
"receiver_tax_id":"1002",
"total":"6949,15",
"receiver_company_name":"Das Company",
"receiver_email":"info#another.com",
"status":0
},
{
"receiver_tax_id":"1001",
"total":"39222,49",
"receiver_company_name":"SAD company",
"receiver_email":"info#mail.com",
"status":1
}
]
Hi, this is my Json data, but I can't deserialize it.
I want to check only "status" value. (first object "status" 0, second object "status" 1).
Example definition:
public class Example
{
[JsonProperty("receiver_tax_id")]
public string receiver_tax_id { get; set; }
[JsonProperty("total")]
public string total { get; set; }
[JsonProperty("receiver_company_name")]
public string receiver_company_name { get; set; }
[JsonProperty("receiver_email")]
public string receiver_email { get; set; }
[JsonProperty("status")]
public int status { get; set; }
}
Deserialization code:
var des = (Example)JsonConvert.DeserializeObject(responseString, typeof(Example));
Console.WriteLine(des.status[0].ToString());
Try this code:
public class Receiver
{
public string receiver_tax_id { get; set;}
public string total { get; set;}
public string receiver_company_name { get; set;}
public int status { get; set;}
}
And deserialize looks like follows:
var result = JsonConvert.DeserializeObject<List<Receiver>>(responseString);
var status = result[0].status;
If you only care about checking status you can use the dynamic type of .NET (https://msdn.microsoft.com/en-us/library/dd264741.aspx)
dynamic deserialized = JObject.Parse(responseString);
int status1 = deserialized[0].status;
int status2 = deserialized[1].status;
//
// do whatever
This way you don't even need the Example class.
From your code and JSON sampels it seems the problem is you're actually deserializing a List<Example> rather than a single Example.
I would do two things:
Make your class follow .NET naming conventions, as you already prefixed them with the proper JsonProperty attributes:
public class Example
{
[JsonProperty("receiver_tax_id")]
public string ReceiverTaxId { get; set; }
[JsonProperty("total")]
public string Total { get; set; }
[JsonProperty("receiver_company_name")]
public string ReceiverCompanyName { get; set; }
[JsonProperty("receiver_email")]
public string ReceiverEmail { get; set; }
[JsonProperty("status")]
public int Status{ get; set; }
}
Deserialize a List<Example> using the generic JsonConvert.DeserializeObject<T> overload instead of the non-generic version you're currently using:
var des = JsonConvert.DeserializeObject<List<Example>>(responseString);
Console.WriteLine(des[0].Status);
You're trying to deserialize an array into an Example object. Try doing it to a List instead:
var des = JsonConvert.DeserializeObject(responseString, typeof(List<Example>)) as List<Example>;

How to bind multilevel json data to a repeater in asp.net or converting json data to data table

I want to bind the Json data to the repeater I know only one process that is converting the Json data to data table and then binding data but here I am receiving multilevel json data i do't know how to convert them to data table
input json data:
{"apiAvailableBuses":
[{"droppingPoints":null,"availableSeats":40,"partialCancellationAllowed":false,"arrivalTime":"01:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"07:40PM","location":"K.P.H.B,Beside R.S Brothers","id":"2238"}],"operatorName":"Apple I Bus","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6686","fare":"1000","busType":"Hi-Tech A/c","routeScheduleId":"6686","commPCT":9.0,"operatorId":203,"inventoryType":0},
{
"droppingPoints":null,"availableSeats":41,"partialCancellationAllowed":false,"arrivalTime":"06:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"08:00PM","location":"Punjagutta,","id":"2241"}],"operatorName":"Royalcoach Travels","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6736","fare":"800","busType":"VOLVO","routeScheduleId":"6736","commPCT":9.0,"operatorId":243,"inventoryType":0}
I am trying to convert it to data table by
public void getavailablebuses()
{
string url = string.Format(HttpContext.Current.Server.MapPath("files/getavailablebuses.json"));
using (WebClient client = new WebClient())
{
string json = client.DownloadString(url);
var result = JsonConvert.DeserializeObject<RootObject>(json);
string mm = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
// var boardingpoint = JObject.Parse(mm).SelectToken("boardingPoints").ToString();
var Availablebuses = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
DataTable dt = (DataTable)JsonConvert.DeserializeObject(Availablebuses, (typeof(DataTable)));
}
public class apiresult
{
public string message { get; set; }
public string success { get; set; }
}
public class RootObject
{
public apiresult apiStatus;
public List<apiAvailableBuses> apiAvailableBuses{ get; set; }
// public string apiAvailableBuses { get; set; }
}
public class apiAvailableBuses
{
public string serviceId { get; set; }
public string fare { get; set; }
public string busType { get; set; }
public string departureTime { get; set; }
public string operatorName { get; set; }
public string cancellationPolicy { get; set; }
public List<boardingpoints> boardingpoints { get; set; }
public string droppingPoints { get; set; }
public string inventoryType { get; set; }
public string routeScheduleId { get; set; }
public int availableSeats { get; set; }
public string arrivalTime { get; set; }
public Boolean idProofRequired { get; set; }
public Boolean partialCancellationAllowed { get; set; }
public int operatorId { get; set; }
public double commPCT { get; set; }
public string mTicketAllowed { get; set; }
}
public class boardingpoints
{
public string location { get; set; }
public string id { get; set; }
public string time { get; set; }
}
public class cancellationPolicy
{
public string cutoffTime { get; set; }
public string refundInPercentage { get; set; }
}
Here in the data table I am unable to get the boarding points, dropping points and cancellation policy
if I load cancellation policy as list or JObject I am getting error
so here I am loading cancellation policy as string.
but I am unable to load boarding points and dropping points.
Please help with this I am scratching my head from two days. Thanks in advance
"I know only one method to bind data to a repeater i.e data table." So this is a perfect opportunity to learn other ways, wouldn't you say?
Why don't you work with the result of JsonConvert.DeserializeObject<RootObject>(json);? This is a RootObject that has a property called apiAvailableBuses which seems to be exactly what you need to bind to your repeater, no?
By the way, a bit of code review:
apiresult and apiAvailableBuses violate Microsoft's rules WRT class names: those should be in PascalCase. Same for the properties of apiresult, e.g. message and success. Same for the properties of apiAvailableBuses.
RootObject has a public field: apiStatus. That probably needs to be a a property with a getter/setter.
Moreover, apiAvailableBuses is plural, which is incorrect, since the data therein is of only one bus. Same for boardingpoints: the class contains data for a single point, not multiple.
Be consistent: if you use string, then also use bool and not Boolean.

Categories

Resources