Consuming Varying JSON Response - c#
I am having trouble understanding how to deserialze a JSON string into a class that's coming back from an API I am calling...
Normally, I copy the returned JSON and in Visual Studio I paste special as JSON to Class. It normally works perfectly.
But, with this API the class that is generated contains hardcoded values that might be different the next time I call the API...
This is the JSON that comes back from the API:
{"content":{"type":"getTips_answer","total":61,"scan":1,"tips":{"2360626":[["3","4","6","8","10","25"],["9","11","22","27","34","40"],["4","12","25","27","29","30"],["4","6","7","10","41","47"],["14","17","20","40","41","42"],["17","20","22","26","30","41"],["1","3","18","21","28","39"],["5","10","13","19","25","39"],["17","25","33","38","42","44"],["5","11","16","25","43","45"],["5","9","25","27","38","44"],["7","19","27","32","46","48"],["20","21","28","34","37","48"],["10","12","18","35","43","47"],["3","6","9","17","29","42"],["22","26","28","36","43","47"],["7","13","24","30","45","48"],["3","5","14","19","23","27"],["9","14","15","16","22","40"],["10","18","26","36","41","46"],["2","19","23","33","38","42"]],"2360710":[["1","15","17","21","25","33"]],"2361097":[["1","3","5","27","35","41"],["3","11","12","24","27","48"],["8","11","13","33","34","48"],["2","10","29","31","41","46"]],"2362535":[["10","15","33","35","36","44"],["5","8","11","18","26","44"]],"2363152":[["6","7","10","13","35","37"],["1","9","14","29","42","49"],["23","24","26","32","35","45"],["1","2","11","18","22","39"]],"2363573":[["8","11","16","18","34","36"],["12","13","23","25","27","35"],["2","7","13","23","41","49"],["3","6","9","15","21","41"],["9","10","16","20","30","34"],["15","18","40","44","46","48"]],"2363902":[["17","19","24","26","33","48"]],"2364026":[["8","17","20","33","34","47"]],"2364405":[["10","17","23","38","41","45"],["9","13","27","33","36","41"]],"2365222":[["4","5","7","9","18","24"],["10","12","16","26","43","45"],["1","5","24","26","43","47"],["11","12","17","20","36","48"],["3","11","13","17","20","27"],["2","6","28","38","42","46"],["9","13","19","20","25","31"],["2","5","7","8","25","27"],["1","19","21","23","33","36"],["17","19","23","33","38","47"],["14","27","28","32","39","42"],["18","26","30","32","42","46"]],"2365522":[["2","24","25","31","42","48"],["13","16","31","39","43","45"]],"2365651":[["7","20","22","35","40","41"],["5","13","20","30","43","47"],["5","16","18","31","34","44"],["6","8","15","17","44","45"],["7","11","26","27","29","47"]]},"success":true,"errors":[]}}
This is the class that Visual Studio generates from the above JSON:
public class Rootobject
{
public Content content { get; set; }
}
public class Content
{
public string type { get; set; }
public int total { get; set; }
public int scan { get; set; }
public Tips tips { get; set; }
public bool success { get; set; }
public object[] errors { get; set; }
}
public class Tips
{
public string[][] _2360626 { get; set; }
public string[][] _2360710 { get; set; }
public string[][] _2361097 { get; set; }
public string[][] _2362535 { get; set; }
public string[][] _2363152 { get; set; }
public string[][] _2363573 { get; set; }
public string[][] _2363902 { get; set; }
public string[][] _2364026 { get; set; }
public string[][] _2364405 { get; set; }
public string[][] _2365222 { get; set; }
public string[][] _2365522 { get; set; }
public string[][] _2365651 { get; set; }
}
My problem is that if you look at the Tips class it contains values like _2360626 which might not be there next time.
How to I write a class that I can deserialize this string into that is "dynamic"? if that is the right description?
Thanks
Just declare tips as Dictionary<string,List<List<string>>>
var obj = JsonConvert.DeserializeObject<RootObject>(json); //Json.Net
//or
//var obj = new JavaScriptSerializer().Deserialize<RootObject>(json);
public class Content
{
public string type { get; set; }
public int total { get; set; }
public int scan { get; set; }
public Dictionary<string,List<List<string>>> tips { get; set; }
public bool success { get; set; }
public List<object> errors { get; set; }
}
public class RootObject
{
public Content content { get; set; }
}
I think you'll have to put aside this idea of creating a statically typed class in C# to model this JSON. JSON (and javascript) is not typed so there's not guarantee that it will always fit into such a class (as you've discovered).
I would suggest using one of the C# JSON parsing libraries you'll find referenced here:
http://json.org/
JSON.Net (http://james.newtonking.com/pages/json-net.aspx) sounds popular.
Link that in your project and then use it to dynamically parse the JSON you're receiving from your API call and then do whatever you need to do with the result.
Related
Formatted Json Deserialize throws Exception
I was experiencing some to deserilize a json file until I realized the reason was that the file was formatted, prettified, beautified etc. Using Newtonsoft.Json library and calling JsonConvert.DeserializeObject<myObject>(mystring); throws a JsonSerializationException: {"Unexpected end when reading JSON. Path '', line 1, position 1."} Then, when I repeated the operation, but with a minified, compacted, etc version of the same file it worked. Is there a way to use this libray and deserialize data in both scenarios? Thank you!
Your json is Valid, your model should be like this public class Step { public int StepID { get; set; } public string Description { get; set; } public List<int> ShutMoves { get; set; } public List<int> FeatIDs { get; set; } public List<int> ExpSettings { get; set; } } public class Part { public int PartID { get; set; } public string Description { get; set; } public bool Moving { get; set; } public List<int> FeatIDs { get; set; } } public class Feat { public int FeatID { get; set; } public int CamID { get; set; } public int CamFeatID { get; set; } public int PartID { get; set; } } public class RootObject { public List<Step> Steps { get; set; } public List<Part> Parts { get; set; } public List<Feat> Feats { get; set; } }
Small Example - public void JsonDeserializeTesting() { var testingModal = new TestingModal{Id = 1,Name = "Eminem",}; var serializeObject = JsonConvert.SerializeObject(testingModal); var deserializeObject = JsonConvert.DeserializeObject<TestingModal> (serializeObject); Console.WriteLine($"{deserializeObject}"); } public class TestingModal{ public long Id { get; set; } public string Name { get; set; } } I hope this will give you abstract view of how to use Deserialize.
This was a mistake from my side. The string I was deserializing was obtained by using ReaLine(). So my code was parsing only the first line of the file. ReadToEnd() from the stream or even File.ReadAllText fixes the issue. Thank you for the help.
Deserialise a Kraken JSON in C#
I used to be loading data from Cryptocompare's API. This post got me what I wanted for Cryptocompare. Parsing Cryptocompare API Json data in C# However, I notice that this API is not bulletproof, it's not always returning an answer. So I want to use Kraken itself. Now I am trying to deserialise the new JSON but this is not straightforward as Cryptocompare's JSON. Here is an example JSON: https://api.kraken.com/0/public/OHLC?pair=ETHUSD&interval=30 {"error":[],"result":{"XETHZUSD":[[1519236000,"825.94","846.00","825.94","845.00","835.62","858.29381033",708],[1519237800,"846.00","848.84","835.55","836.00","844.31","647.42747317",731],[1519239600,"836.00","841.09","830.76","834.89","835.13","1051.44905097",609],[1520530200,"706.24","710.43","701.90","704.59","707.70","1763.41692283",459]],"last":1520528400}} I have not been able to deserialise this JSON. Solved!!! final solution: var Results_Exchange_Kraken = JsonConvert.DeserializeObject<DataRoot_Kraken>(Content_Exchange_Kraken); var price_data_kraken = Results_Exchange_Kraken.result.XETHZUSD; public class Kraken_Result { public List<List<object>> XETHZUSD { get; set; } public int last { get; set; } } public class DataRoot_Kraken { public List<object> error { get; set; } public Kraken_Result result { get; set; } } Thank you! I'll bookmark the URL.
Use this Model to de-serialise your data public class Result { public List<List<object>> XETHZUSD { get; set; } public int last { get; set; } } public class RootObject { public List<object> error { get; set; } public Result result { get; set; } } Model Generated by Model Generator Then use NewtonSoft for c# to de-serialise your data E.g. RootObject tmp = JsonConvert.DeserializeObject<RootObject>("JSON String here"); final solution: var Results_Exchange_Kraken = JsonConvert.DeserializeObject<DataRoot_Kraken>(Content_Exchange_Kraken); var price_data_kraken = Results_Exchange_Kraken.result.XETHZUSD; public class Kraken_Result { public List<List<object>> XETHZUSD { get; set; } public int last { get; set; } } public class DataRoot_Kraken { public List<object> error { get; set; } public Kraken_Result result { get; set; } }
C# Parsing JSON String
I have tried countless methods to Parse my JSON string (Steam Public Data), yet nothing seems to work. I just want to be able to extract values from the string. For Example, obtaining the value of personaname which would return SlothGod. I have JSON.NET installed in my project. Here is my JSON: { "response": { "players": [ { "steamid": "76561198301407459", "communityvisibilitystate": 3, "profilestate": 1, "personaname": "SlothGod", "lastlogoff": 1508389707, "commentpermission": 1, "profileurl": "http://steamcommunity.com/id/sleuthgud/", "avatar": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/09/09cea52b91136fb3306c57771a746db2823b91ba.jpg", "avatarmedium": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/09/09cea52b91136fb3306c57771a746db2823b91ba_medium.jpg", "avatarfull": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/09/09cea52b91136fb3306c57771a746db2823b91ba_full.jpg", "personastate": 0, "realname": "Josh", "primaryclanid": "103582791460168790", "timecreated": 1462086929, "personastateflags": 0, "loccountrycode": "AU", "locstatecode": "QLD" } ] } } Main method suggested to me: public class Details { public string personaname { get; set; } } private void GetSteamDetails() { var data = Newtonsoft.Json.JsonConvert.DeserializeObject<Details>(SteamDetailsJson); SteamName = data.personaname; } This is placed before Page_Load(). I then call GetSteamDetails(); when I want to fetch the name.
After my question being down voted, I decided to not give up on this problem. After extensive research, trial and error, and YouTube tutorials which are the most helpful IMO. I found that the data was containing a JSON array, and yes I will admit, I was confused with this, but the answer was to simply treat it like a C# array and add [1] to the end of players. Details details = new Details(); public class Details { public string avatar { get; set; } public string avatarmedium { get; set; } public string avatarfull { get; set; } public string realname { get; set; } public string personaname { get; set; } public string steamid { get; set; } } private void GetSteamDetails() { var SteamDetails= JsonConvert.DeserializeObject<dynamic>(SteamDetailsJson); avatar = SteamDetails.response.players[1].avatar.ToString(); personaname = SteamDetails.response.players[1].personaname.ToString(); }
Based on the JSON string you provided, you should have the following C# classes to support it, or to deserialize the JSON object values into: I used this link to generate the classes. public class Player { public string steamid { get; set; } public int communityvisibilitystate { get; set; } public int profilestate { get; set; } public string personaname { get; set; } public int lastlogoff { get; set; } public int commentpermission { get; set; } public string profileurl { get; set; } public string avatar { get; set; } public string avatarmedium { get; set; } public string avatarfull { get; set; } public int personastate { get; set; } public string realname { get; set; } public string primaryclanid { get; set; } public int timecreated { get; set; } public int personastateflags { get; set; } public string loccountrycode { get; set; } public string locstatecode { get; set; } } public class Response { public List<Player> players { get; set; } } public class RootObject { public Response response { get; set; } } Then, using Newtonsoft.Json, you can deserialize the JSON object into your C# classes as follow: JsonConvert.DeserializeObject<RootObject>("yourJsonString");
You mention that Newtonsoft.Json already referenced in the project. Use class to represent json data structure, then you can easy deserialize it. You can use only properties you need in the class. public class Player { public string personaname { get; set; } } var player = Newtonsoft.Json.JsonConvert.DeserializeObject<Player>(jsonString); // use player.personaname For updates question create classes which represent your data structure public class Team { public List<Player> players { get; set; } } public class Response { public Team response { get; set; } }
You can use http://json2csharp.com/ to generate a class automatically from a JSON string.
Unable to deserialize JSON in c#
I am getting the below JSON in response from a REST API. { "data":{ "id":123, "zoneid":"mydomain.com", "parent_id":null, "name":"jaz", "content":"172.1 6.15.235", "ttl":60, "priority":null, "type":"A", "regions":[ "global" ], "system_record":false, "created_at":"2017-09-28T12:12:17Z", "updated_at":"2017-09-28T12:12:17Z" } } and trying to resolve using below code but that doesn't result in a correctly deserialized type. var model = JsonConvert.DeserializeObject<ResponseModel>(response); below is a class according the field I received in JSON response. public class ResponseModel { public int id { get; set; } public string zone_id { get; set; } public int parent_id { get; set; } public string name { get; set; } public string content { get; set; } public int ttl { get; set; } public int priority { get; set; } public string type { get; set; } public string[] regions { get; set; } public bool system_record { get; set; } public DateTime created_at { get; set; } public DateTime updated_at { get; set; } } What is missing?
You're missing a wrapper class. public class Wrapper { public ResponseModel data {get;set} } and then do: var model = JsonConvert.DeserializeObject<Wrapper>(response).data; to get the instance of your ResponseModel out the data property. You can deduct this from your json: { "data": { "id":123, /*rest omitted */ } } The type that will receive this JSON needs to have a property named data. The suggested Wrapper class acts as that type.
According to json2csharp website, your model seems to be incorrect. Try this one : public class ResponseModel { public int id { get; set; } public string zoneid { get; set; } public object parent_id { get; set; } public string name { get; set; } public string content { get; set; } public int ttl { get; set; } public object priority { get; set; } public string type { get; set; } public List<string> regions { get; set; } public bool system_record { get; set; } public DateTime created_at { get; set; } public DateTime updated_at { get; set; } } public class RootObject { public ResponseModel data { get; set; } }
Here a cool trick you can do in Visual Studio 2015-2017 where it generates the the correct class if you just copy the JSON (ctrl + c). You need to create a new class in visual studio and once inside the class go to Edit menu -> Paste special -> paste JSON As Classes. Steps to generate json class This will generate the C# object for that json for you and save you all the hassle :)
Your model does not match your response - it matches the data property. Simply wrap another object round it public class ResponseData { public ResponseModel Data {get; set; { } and then var model = JsonConvert.DeserializeObject<ResponseData>(response);
Deserializing list objects, properties returning as null
I'm trying to POST data to an API which should accept a List<UpdatePointHistory>. The size of the list is correct but the properties of the objects are blank. public class UpdatePointHistory { string Tree { get; set; } string FruitCount { get; set; } string Observations { get; set; } int PrivateId { get; set; } } public void Post([FromBody]List<UpdatePointHistory> updates) { //Do some sort of auth for god sake Console.WriteLine("test"); } The data I'm posting: And the object returning from the API:
All your properties are private. They need to be public so the model binder knows what to populate and has access to them. public class UpdatePointHistory { public string Tree { get; set; } public string FruitCount { get; set; } public string Observations { get; set; } public int PrivateId { get; set; } }