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
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
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!
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.
[
{
"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>;
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.