Deserialize Object into a class does not work - c#

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.

Related

How do I convert a JSON DateTime format to a C# DateTime format from an API call

I'm currently building a project that retrieves API data and saves it into a database. Everything is working fine except for the DateTime values in the API. I have a class that uses RestSharp to obtain the API data then it uses NewtonSoft.Json to derserialize the API data into a JSON format which is then stored into a temporary DTO class file. Here is the API method.
public static void getAllRequestData()
{
var client = new RestClient("[My API URL]");
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
AllRequests.Rootobject result = JsonConvert.DeserializeObject<AllRequests.Rootobject>(rawResponse);
}
}
Now here is the DTO file (AllRequests) that will temporarily store the Converted JSON data.
public class AllRequests
{
public class Rootobject
{
public Operation Operation { get; set; }
}
public class Operation
{
public Result Result { get; set; }
public Detail[] Details { get; set; }
}
public class Result
{
public string Message { get; set; }
public string Status { get; set; }
}
public class Detail
{
[Key]
public int Id { get; set; }
public string Requester { get; set; }
public string WorkOrderId { get; set; }
public string AccountName { get; set; }
public string CreatedBy { get; set; }
public string Subject { get; set; }
public string Technician { get; set; }
public string IsOverDue { get; set; }
public string DueByTime { get; set; }
public string Priority { get; set; }
public string CreatedTime { get; set; }
public string IgnoreRequest { get; set; }
public string Status { get; set; }
}
}
The lines of code in Details that I want to be DateTime formats are "DueByTime" and "CreatedTime" instead of being String values. Currently they're only holding JSON format DateTime values in a String such as "1477394860065".
I've tried making "public string CreatedTime { get; set; }" to "public DateTime CreatedTime { get; set; }" However that only returned an error since it's JSON format. How could I rectify this issue so that it's stored in the DTO correctly in a DateTime format? Because ideally I want to scaffold this class file into a table so it can hold data in a database.
For more context to this, here's what I want rectified in my Database.
I want there to be a DateTime shown instead of a long list of numbers like there is here under Createby and DueBy.
Any help would be appreciated.
[EDIT] added the unix time format compliance[/EDIT]
Just putting in code what #Fildor said
public long CreatedTime { get; set; }
[JsonIgnore] // will ignore the property below when serializing/deserializing
public DateTimeOffset CreatedTimeDate {
// Don't need a setter as the value is directly get from CreatedTime property
get {
return DateTimeOffset.FromUnixTimeMilliseconds(CreatedTime);
}
}
Used also this answer to convert to DateTime as asked, using the local time.
Here is how you convert to DateTime if you don't need the offset : https://learn.microsoft.com/fr-fr/dotnet/standard/datetime/converting-between-datetime-and-offset

How can I deserialise a JSON result where its Root is a unique ID into an Object class

I am currently trying to learn to work with API systems using C# .net core 3 and Newtonsoft.
The following call to Steam API is what I am using
for specific game details. For example http://store.steampowered.com/api/appdetails?appids=72850
This returns JSON similar to this ( I have cut it down for simplicity )
{
"72850": {
"success": true,
"data": {
"type": "game",
"name": "The Elder Scrolls V: Skyrim",
"steam_appid": 72850,
"required_age": 0,
"is_free": false
}
}
}
Each return has the unique ID as the root in this case 72850 and I am at a loss on how to map this into an object class so I can process this data. The "data" element is what I am really interested in but as a beginner, I am at a loss.
This API indexes its response using the internal Identifier of the Item requested.
This is a common scenario and it's also a quite efficient method to organize objects based on an Indexer, which can then be used to store or retrieve these objects, from a database, for example.
A common way to deserialize JSON object indexed like this, is to use a Dictionary, where the Key is Indexer and the Value the RootObject of the class structure (the Model) that further describes the JSON properties.
Some notes on the current JSON:
The API looks like it's built to represent the JSON on a HTML document, since the internal strings are formatted ready for presentation on a HTML page. This can be less useful when used elsewhere and can also create a problem when deserializing.
I've added a trivial clean-up, replacing what can cause a problem for sure:
json = json.Replace(#"\/", "/").Replace(#"\t", "");
I've added some more properties and classes to those presented in the question: it may be useful to see when a JsonProperty attribute is needed and when is it's not. For example: the [JsonProperty("type")] attribute is added to the public string GameType { get; set; } property, since Type is a keyword that may be misinterpreted, as is Name etc.
Json.Net is not case sensitive, so the JSON property background can be assigned to a .Net property public Uri Background { get; set; } without problem.
A couple of WebSites that provide a free service to format, validate and convert JSON object to a class model:
JsonFormatter - Formatting, validation
QuickType - Multi-language Class Model generator
Download the JSON using the WebClient.DownloadString() method, clean up the JSON and deserialize:
var steamUri = new Uri("https://store.steampowered.com/api/appdetails?appids=72850")
string json = new WebClient(steamUri).DownloadString();
json = json.Replace(#"\/", "/").Replace(#"\t", "");
var steamObj = JsonConvert.DeserializeObject<Dictionary<long, SteamApps.SteamAppDetails>>(json);
Class structure:
public class SteamApps
{
public class SteamAppDetails
{
public bool Success { get; set; }
public Data Data { get; set; }
}
public class Data
{
[JsonProperty("type")]
public string GameType { get; set; }
[JsonProperty("name")]
public string GameName { get; set; }
[JsonProperty("steam_appid")]
public long SteamAppid { get; set; }
[JsonProperty("required_age")]
public long RequiredAge { get; set; }
[JsonProperty("is_free")]
public bool IsFree { get; set; }
[JsonProperty("short_description")]
public string ShortDescription { get; set; }
[JsonProperty("supported_languages")]
public string Languages { get; set; }
[JsonProperty("header_image")]
public string HeaderImage { get; set; }
public string WebSite { get; set; }
[JsonProperty("price_overview")]
public PriceOverview PriceOverview { get; set; }
public Dictionary<string, bool> Platforms { get; set; }
public List<Screenshot> Screenshots { get; set; }
public Uri Background { get; set; }
public List<Category> Categories { get; set; }
}
public class PriceOverview
{
public string Currency { get; set; }
public long Initial { get; set; }
public long Final { get; set; }
[JsonProperty("discount_percent")]
public decimal DiscountPercent { get; set; }
[JsonProperty("initial_formatted")]
public string InitialFormatted { get; set; }
[JsonProperty("final_formatted")]
public string FinalFormatted { get; set; }
}
public partial class Screenshot
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("path_thumbnail")]
public string PathThumbnail { get; set; }
[JsonProperty("path_full")]
public string PathFull { get; set; }
}
public partial class Category
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
}
}
Since you only need the "Data" element from the json, it is fairly simple using Newtonsoft. First make a class with all the fields that the Data element contains as shown below:
public class Data
{
public string Type { get; set; }
public string Name { get; set; }
public long Steam_AppId { get; set; }
public int Required_Age { get; set; }
public bool Is_Free { get; set; }
}
Now in order to map the json response, which I'm assuming is stored in a string at the moment, you have to Deserialize it to map to your C# class. And you can do that very easily:
Edit: A more elegant solution which avoids all the string manipulation nuisance
//You already have this but I created it in order to test
string jsonResult = "{ \"72850\": " +
"{ \"success\": true, \"data\": " +
"{ \"type\": \"game\", \"name\": \"The Elder Scrolls V: Skyrim\", " +
"\"steam_appid\": 72850, \"required_age\": 0, \"is_free\": false } }";
//JObject is a class in Newtonsoft library for handling json objects
JObject jObject = JObject.Parse(jsonResult);
//Since you're sending a request to the api, either you already have the id
//"72850" or can extract it easily from uri. This line gets data's value
//by 1st searching for key = "72850" and then within that a key = "data"
JToken dataToken = jObject["72850"]["data"];
Data data = dataToken.ToObject<Data>();
Reference: https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm
Older solution
//getting the value portion of data element/key
string jsonData = "{" + jsonResult.Substring(jsonResult.IndexOf("\"type"));
//removing the extra } from the end
jsonData = jsonData.TrimEnd('}');
//map the json string to a C# object
var dataObj = JsonConvert.DeserializeObject<Data>(jsonData);
So now you'll see the json values mapped to your Data object which in this case is dataObj. Feel free to ask questions if anything's not clear. Cheers!

How can I convert JSON to an object?

I'm very new to C# and playing around with Visual Studio and Xamarin.
I have a web service where I get a JSON result from looking like this:
{"Vorname": "MYNAME", "AusweisNr": "894", "MitgliedsNr": "33203", "returnstr": "None", "returncode": "0"}
What I'm trying to do is to use the data I get to fill some text fields with, but I don't understand how to get it converted. I've already played around a bit with JsonConvert but couldn't get it working.
Create a class with those properties:
public class SomeMeaningfulName
{
public string Vorname { get; set; }
public string AusweisNr { get; set; }
public string MitgliedsNr { get; set; }
public string returnstr { get; set; }
public string returncode { get; set; }
}
Then you can deserialize the string into that class:
var myObj = JsonConvert.DeserializeObject<SomeMeaningfulName>(yourJsonString);
You can create a simple class like this:
public class Person
{
public string Vorname { get; set; }
public string AusweisNr { get; set; }
public string MitgliedsNr { get; set; }
public string returnstr { get; set; }
public string returncode { get; set; }
}
And to deserialize it:
string json = "{'Vorname': 'MYNAME', 'AusweisNr': '894', 'MitgliedsNr': '33203', 'returnstr': 'None', 'returncode': '0'}"
Person person = new JavaScriptSerializer().Deserialize<Person>(json);
In this case I use JavascriptSerializer because it very simple to use but you can also use JSONConverter if you realy need it
In order to convert using JsonConvert, you need to have a class with fields that share the names of your JSON object and they all need to be public. Try this
class MyJsonObject
{
public string Vorname;
public int AusweisNr;
public int MitgliedsNr;
public string returnstr;
public int returncode;
}
If you want, you could also make it a public property rather than a variable. To convert, you need to do something like this.
MyJsonObject obj= JsonConvert.DeserializeObject<MyJsonObject>(jsonData);
Where jsonData is a string containing your JSON code. You can then copy all the data to a text field.
Get your JSON string and set in this WebSite, this website will create a class object for you, take this object and put in your project.
example:
public class RootObject // object name
{
//atributtes names
public string Vorname { get; set; }
public string AusweisNr { get; set; }
public string MitgliedsNr { get; set; }
public string returnstr { get; set; }
public string returncode { get; set; }
}
So you will dowloand this JSON and put in a String var
example:
var Apiurl = "http://youAPI.com/something/something/";
var JSONString= new System.Net.WebClient().DownloadString(Apiurl);//this will download all text what the Apiurl return
After that, you will put convert/Deserialize your JsonString in a object.
RootObject objectJSON = JsonConvert.DeserializeObject<RootObject>(JSONString);
whats happen in this last code?
yourJsonObject nameForThisObject = JsonConvert.DeserializeObject<yourObjectJsonClass>(yourJsonString);
note: your ObjectJsonClass(my RootObject) must have the sames Json's attributes.

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