Newtonsoft.Json not serializing object as expected - error 400 - c#

I'm trying to send a post request with a json string of an object I have created. However after serializing my c# object and posting I get a 400 error (problems parsing JSON)
I'm using the Newtonsoft.Json dll to serialize my object. Here is the object I am serializing:
public class CreateRepository
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("homepage")]
public object Homepage { get; set; }
[JsonProperty("gitignore_template")]
public string GitIgnoreTemplate { get; set; }
[JsonProperty("license_template")]
public string LicenceTemplate { get; set; }
[JsonProperty("private")]
public bool Private { get; set; }
[JsonProperty("has_projects")]
public bool HasProjects { get; set; }
[JsonProperty("has_issues")]
public bool HasIssues { get; set; }
[JsonProperty("has_template")]
public bool HasTemplate { get; set; }
[JsonProperty("has_wiki")]
public bool HasWiki { get; set; }
}
I am then serializing an instance of the object like so:
var content = JsonConvert.SerializeObject(repository);
This then generates the json string below:
{
\"name\": \"Test\",
\"description\":null,
\"homepage\":null,
\"gitignore_template\":null,
\"license_template\":null,
\"private\":false,
\"has_projects\":false,
\"has_issues\":false,
\"has_template\":false,
\"has_wiki\":false}
}
I get the following back after attempting to post the request:
{
"message": "Problems parsing JSON",
"documentation_url": "https://developer.github.com/v3/repos/#create"
}
Does anyone know why my object has been serialized in this way?
Update:
I can deserialize the object using JSON.Net without any errors.
The url I'm posting to is as follows:
https://api.github.com/user/repos
this is how I'm sending the request:
var response = await _httpClient.PostAsJsonAsync("user/repos", content);

The problem is that "has_template" is unknown at Github side and probably should be "is_template". See the link you got back in the response of your request for the correct parameter names. So you are not using the correct property names/name attributes in your Class. Serialization is not the issue.

Related

RestSharp not deserializing a string (always null)

I currently tried to get serialized response from a RestSharp PostAsync call like in
var responseData = Client.PostAsync<Data>(request).Result;
Now, this is what I receive:
{
"status":1,
"success":"message transmitted",
"available":19215,
"message_ids":"26684730:56798"
}
and this is the "Data" class:
public class Data
{
[JsonProperty("status")]
public int Status { get; set; }
[JsonProperty("success")]
public string Success { get; set; }
[JsonProperty("available")]
public int Available { get; set; }
[JsonProperty("message_ids")]
public string MessageIds { get; set; }
[JsonProperty("error")]
public string Error { get; set; }
}
I don't know why, but the property message_ids is always null!?
May this be caused by the : in the string, and my this be a bug in RestSharp?
Here is what "Data" looks like:
for restsharp you need JsonPropertyName attribute
[JsonPropertyName("message_ids")]
public string MessageIds { get; set; }
or if you want to use JsonProperty you will have to use Newtonsoft.Json
var response = client.ExecuteAsync(request).Result;
//if you have async method better to use
var response = await client.ExecuteAsync(request);
Data data = JsonConvert.DeserializeObject<Data>(response.Content);

can not deserialize Json Object to Type

I have an below Json object,I am trying to Deserialize json object to "type" but its shows an error message as
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List`1[KHDataSynch.response]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be deserialized from a JSON
object. JsonObjectAttribute can also be added to the type to force it
to deserialize from a JSON object. Path 'response', line 2, position
14.
Please check my below code and advise how to solve this issue.
Json Data :
{
"response":
{
"uri": "\/api\/junaid#khindia.com",
"action": "MYWORKSPACELIST",
"result": [{"workspaceId":"2102454000005681734","workspaceName":"Zoho Desk Analytics (Sample)-Copy","workspaceDesc":"Zoho Desk Analytics reporting database providing insightful reports and dashboards on the Help desk data collected.","orgId":"698551553","createdTime":"1596886142038","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000005398071","workspaceName":"MyData","workspaceDesc":"","orgId":"698551553","createdTime":"1596095878304","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000005201413","workspaceName":"GloveOrder","workspaceDesc":"","orgId":"698551553","createdTime":"1595582160570","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000003663782","workspaceName":"TAD","workspaceDesc":"","orgId":"698551553","createdTime":"1591781832434","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000003605784","workspaceName":"Glove Factory","workspaceDesc":"This workspace for factory people to develop Reports and Dashboards","orgId":"698551553","createdTime":"1591618269812","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000001881026","workspaceName":"FWD","workspaceDesc":"This is for Shoes Division","orgId":"698551553","createdTime":"1583817905690","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000664009","workspaceName":"HO Details","workspaceDesc":"","orgId":"698551553","createdTime":"1580642044086","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000323397","workspaceName":"KH Retail","workspaceDesc":"","orgId":"698551553","createdTime":"1578720947711","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000319814","workspaceName":"H & S","workspaceDesc":"","orgId":"698551553","createdTime":"1578664170637","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000245988","workspaceName":"Teamwork Projects - Sample","workspaceDesc":"","orgId":"698551553","createdTime":"1578224003870","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000245069","workspaceName":"Facebook Page competitive Analytics (Sample)","workspaceDesc":"Facebook Competitive Analytics workspace providing insightful comparison reports and dashboards from the data collected from your competitors.","orgId":"698551553","createdTime":"1578223755327","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000239193","workspaceName":"Shopify Analytics - Sample","workspaceDesc":"Shopify Analytics workspace providing insightful reports and dashboards on the data collected.","orgId":"698551553","createdTime":"1578223215548","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000228568","workspaceName":"Zoho Finance Advanced Analytics (Sample)","workspaceDesc":"Zoho Finance Analytics reporting database providing insightful reports and dashboards on the data collected.","orgId":"698551553","createdTime":"1578223092773","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000227303","workspaceName":"Super Store Sales","workspaceDesc":"Super Store Sales database with sales data for the last 5 years","orgId":"698551553","createdTime":"1578222583948","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000216894","workspaceName":"Zoho People - Sample-Copy","workspaceDesc":"","orgId":"698551553","createdTime":"1578221159551","createdBy":"junaid#khindia.com","isDefault":false},{"workspaceId":"2102454000000044365","workspaceName":"Gloves","workspaceDesc":"This is for Gloves Data","orgId":"698551553","createdTime":"1576594180567","createdBy":"junaid#khindia.com","isDefault":true},{"workspaceId":"2102454000000004001","workspaceName":"LGD","workspaceDesc":"","orgId":"698551553","createdTime":"1576246723570","createdBy":"junaid#khindia.com","isDefault":false}]
}
}
C# Code :
public class result
{
public string workspaceId { get; set; }
public string workspaceName { get; set; }
public string workspaceDesc { get; set; }
public string orgId { get; set; }
public string createdTime { get; set; }
public string createdBy { get; set; }
public bool isDefault { get; set; }
}
public class response
{
public string uri { get; set; }
public string action { get; set; }
public List<result> result { get; set; }
}
public void GetWorkSpaceList(IReportClient rc)
{
try
{
string uri = rc.GetURI(EMAIL);
string result = rc.MyWorkspaceList(uri, null);
**List<response> res = JsonConvert.DeserializeObject<List<response>>(result);**
}
catch (Exception Ex)
{
XtraMessageBox.Show(Ex.Message);
}
}
A couple of issues:
Your outer JSON structure is an object, not a list - which is what the error message is telling you. It can't convert something which isn't a list into a C# list structure.
You're mising an outer class to represent the outer JSON object - all you've got is the result and response parts - but they are both structures within the outer wrapper.
You need this class structure:
public class Result {
public string workspaceId { get; set; }
public string workspaceName { get; set; }
public string workspaceDesc { get; set; }
public string orgId { get; set; }
public string createdTime { get; set; }
public string createdBy { get; set; }
public bool isDefault { get; set; }
}
public class Response {
public string uri { get; set; }
public string action { get; set; }
public List<Result> result { get; set; }
}
public class Root {
public Response response { get; set; }
}
(auto-generated by pasting your JSON into https://json2csharp.com/ - it's a very handy tool.)
and then you can write
Root data = JsonConvert.DeserializeObject<Root>(result);
//and to get a specific piece of data, you could write, for example:
var action = data.response.action;

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!

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.

Cannot deserialize the current JSON array in C#

I'm attempting to switch from VB.NET to C#; however I'm having some issues with JSON. I'm attempting to deserialize a JSON array. However, I get this error:
Cannot deserialize the current JSON array
Here's the class I'm deserializing into:
public class ReturnObject
{
public int id { get; set; }
public string name { get; set; }
public string url { get; set; }
public bool thumbnailFinal { get; set; }
public string thumbnailUrl { get; set; }
public object bcOverlayUrl { get; set; }
public object personalServerOverlayUrl { get; set; }
}
Deserialize code:
Debug.WriteLine(JsonConvert.DeserializeObject<ReturnObject>(richTextBox1.Text));
Here's the web URL to the JSON I'm attempting to retrieve.
http://www.roblox.com/place-thumbnails?params=[{placeId:1818}]
You're trying to deserialize a JSON array into just a single object, which can't be done.
Change your deserialization code to this:
var deserialized = JsonConvert.DeserializeObject<ReturnObject[]>(richTextBox1.Text)
To see the results:
foreach(var obj in deserialized)
{
Debug.WriteLine(obj.id);
}

Categories

Resources