ASP.NET API binding value from POST - c#

I would like to ask somebody, how to correct prepare collection of classes to binding values from [FromBody].
I have three classes:
public class Point
{
public int? X {get; set;}
}
public class CollectionPoint
{
public List<Point> Point {get; set;}
}
public class TestBlock
{
public string? Name {get; set;}
public List<CollectionPoint> CollectionPoint {get; set;}
}
Than I have methods for reading JSON object, like:
public string Post([FromBody] TestBlock testBlock)
Finally, I have testing JSON,like:
{
"Name":"Block1",
"CollectionPoint":
[
{
"Point":{"X":"20"},
"Point":{"X":"22"},
"Point":{"X":"25"}
},
{
"Point":{"X":"40"}
}
]
}
But problem is, that this solution doesnt work. Can someone help me? Thank you.

The question is not very clear.
Do you want a collection of Points ?
If so there is an extra class somwhere.
public class Point
{
public int? X {get; set;}
}
public class TestBlock
{
public string? Name {get; set;}
public List<Point> CollectionPoint {get; set;}
}
Do you want a collection of a collection of points?
If so the json is malformed, it should be:
{
"Name":"Block1",
"CollectionPoint":
[
{
"Point":
[
{"X":"20"},
{"X":"22"},
{"X":"25"}
]
},
{
"Point":
[
{"X":"20"}
]
}
]
}

Related

Saving JSON to DataTable

I need to save data retrieved from API to a DataTable. JSON which is returned from API can't be deserialized directly to DataTable using this code:
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
I got an error: Unexpected JSON token when reading DataTable. I read that it's beacuse JSON format is not as it should be. Mine is as follows:
{
"page": 1,
"page_size": 1000,
"items": [
{
"id": "e1b019b9a8bf408c9cb964c29e845104",
"asset_id": "5adb0d87882b4e14b99bde74a967e84c",
"alias": "Concrete Pump Yellow",
"serial_number": "QEQ000123",
"model": {
"name": "Pump C50-HP"
},
"operating_hours": {
"hours": 100,
"unit_driven": true
}
}
]
}
I know I need format like [{..}] but can't find workaround, API returns JSON as above. I can deserialize it using this:
var obj = JsonConvert.DeserializeObject(json);
but how can I now add data to DataTable? I'm looking for a solution for it
What the JsonConvert class does is it materializes your string version of the response into an object. For this to work, your string version has to match the structure of the resulting object or the class needs hints to know how to inflate the object. The runtime is telling you that there is a mismatch and it doesn't know how to resolve it.
There are a few ways to get this done. I prefer an structured approach so I would recommend you create classes to receive the data:
var payload = #"{
""page"": 1,
""page_size"": 1000,
""items"": [
{
""id"": ""e1b019b9a8bf408c9cb964c29e845104"",
""asset_id"": ""5adb0d87882b4e14b99bde74a967e84c"",
""alias"": ""Concrete Pump Yellow"",
""serial_number"": ""QEQ000123"",
""model"": {
""name"": ""Pump C50-HP""
},
""operating_hours"": {
""hours"": 100,
""unit_driven"": true
}
}
]
}";
public class ApiResponse
{
[JsonProperty("page")]
public int Page { get; set; }
[JsonProperty("page_size")]
public int PageSize { get; set; }
[JsonProperty("items")]
public IEnumerable<ApiResponseItem> Items { get; set; }
}
public class ApiResponseItem
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("asset_id")]
public string AssetId { get; set; }
[JsonProperty("alias")]
public string Alias { get; set; }
[JsonProperty("serial_number")]
public string SerialNumber { get; set; }
[JsonProperty("model")]
public ApiResponseModel Model { get; set; }
[JsonProperty("operating_hours")]
public ApiResponseOperatingHours OperatingHours { get; set; }
}
public class ApiResponseModel
{
[JsonProperty("name")]
public string Name { get; set; }
}
public class ApiResponseOperatingHours
{
[JsonProperty("hours")]
public string Hours { get; set; }
[JsonProperty("unit_driven")]
public bool UnitDriven { get; set; }
}
var response = JsonConvert.DeserializeObject<ApiResponse>(payload);
As you can see, the classes use hint attributes to let the deserializer know about the fields. You can then loop through the response.Items enumerable and consume the items as desired.
UPDATE:
For posterity and at the suggestion of #mason, it's important to point out that there is no need to use a DataTable. A quick inspection of the payload reveals the output is a paged version of set of records so it's not equivalent to a data table.
Your issue here is that the json you're deserializing is not a DataTable, its just an Object.
JsonConvert.DeserializeObject(request, typeof(Object)) -> Where Object would be a defined Class with parameter definitions to deserialize the json to, i.e page, page_size, id etc..
Once in this format its fairly easy to coerce it into a DataTable:
https://learn.microsoft.com/en-us/dotnet/api/system.data.datatable?view=net-6.0
The Classes would look something along the lines of:
public class Items
{
public Guid? Id {get;set;}
public Guid? AssetId {get;set;}
public string alias {get;set;}
public string serial_number {get;set;}
public Model model {get;set;}
public OperatingHours operatingHours {get;set;}
}
public class Model
{
public string Name { get;set;}
}
public class OperatingHours
{
public int Hours {get;set;}
public bool Unit_Driven {get;set;}
}
public class OverallObject
{
public int Page {get;set;}
public int PageSize {get;set;}
public List<Items> AllItems {get;set;}
}

"NullReferenceException" in Unity3D when trying deserialize data from JSON

I need to get some data from json file i've got it to the string named dataAsJson, on debugging it looks like that:
{\r\n\t\"question\":\r\n\t[\r\n\t\t{\r\n\t\t\"text\":
\"głośniki\",\r\n\t\t\"correct\": \"speaker\",\r\n\t\t\"answer1\":
\"speaker1\",\r\n\t\t\"answer2\": \"speaker2\",\r\n\t\t\"answer3\":
\"speaker3\"\r\n\t\t},\r\n\t\t{\r\n\t\t\"text\":
\"pustynia\",\r\n\t\t\"correct\": \"desert\",\r\n\t\t\"answer1\":
\"desert1\",\r\n\t\t\"answer2\": \"desert2\",\r\n\t\t\"answer3\":
\"deser3\"\r\n\t\t},\r\n\t\t{\r\n\t\t\"text\":
\"rycerz\",\r\n\t\t\"correct\": \"knight\",\r\n\t\t\"answer1\":
\"knight1\",\r\n\t\t\"answer2\": \"knight2\",\r\n\t\t\"answer3\":
\"knight3\"\r\n\t\t}\r\n\t]\r\n}
And then i use JsonUtility.FromJson(dataAsjJson)
This is my objects classes:
public class Question
{
public string text { get; set; }
public string correct { get; set; }
public string answer1 { get; set; }
public string answer2 { get; set; }
public string answer3 { get; set; }
}
public class RootObject
{
public List<Question> questions { get; set; }
}
As you can see the json body is only the "question" with array.
On Debug.log(dataAsJson) it looks normally:
{
"question":
[
{
"text": "głośniki",
"correct": "speaker",
"answer1": "speaker1",
"answer2": "speaker2",
"answer3": "speaker3"
},
{
"text": "pustynia",
"correct": "desert",
"answer1": "desert1",
"answer2": "desert2",
"answer3": "deser3"
},
{
"text": "rycerz",
"correct": "knight",
"answer1": "knight1",
"answer2": "knight2",
"answer3": "knight3"
}
]
}
I need to convert it succesfully to C# object.
As mentioned by Amy in the comments, your C# class structure doesn't match your JSON, I use http://json2csharp.com/ because it's accurate and quick. Make sure you put [Serializable] above each class so we can transform data structures or object states into a format that Unity can store and reconstruct later read more here. Lastly, I would avoid getters and setters in this structure, it will cause problems with serializing & is recommended by unity to use fields instead.
[Serializable]
public class Question
{
public string text;
public string correct;
public string answer1;
public string answer2;
public string answer3;
}
[Serializable]
public class RootObject
{
public List<Question> question;
}

Deserialize to object with custom object property

I have a class like so:
public class CareTaker
{
public int Id {get; set;}
public string name {get; set;}
public DateTime? DateTrained {get; set;}
public Certification Certification {get; set;}
public List<Certification> ExpiredCertifications {get; set;}
}
public class Certification
{
public int Id {get; set;}
}
and my JSON is like so:
{
"id": 1,
"name": "Dogtor",
"dateTrained": "01 Feb 2017",
"certification": 2,
"expiredCertifications": [1,5]
}
I know usually the JSON for Certification should really be like "certification": { "id": 2}, but, I don't have access to change the JSON so I have to figure out how to convert what I recieve ("certification": 2) to my object... Is there a way I can do this with either JavascriptSerializer or NewtonSoft please?
You could do something like this:
public class CareTaker
{
...
[NotMapped]
[JsonProperty(PropertyName = "certification"]
public int? CertificationId
{
get
{
return Certification?.Id;
}
set
{
Certification = new Certification { Id = value; }
}
}
[JsonIgnore]
public Certification Certification {get; set;}
...
}
To generate properly the classes, I would suggest copying the JSON and open the file where you want to store the classes and in visual studio go to EDIT->Paste Special->Paste JSON As Classes
then you would do something like this:
JavaScriptSerializer ser = new JavaScriptSerializer();
var jsonToClasses = ser.Deserialize<RootObject>(json);

Deserailize JSON string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have JSON in this format:
{
"user": "123#abc",
"filter": [
{
"filterName": "Filter1",
"condition": "1",
"values": [
"123"
]
},
{
"filterName": "Filter2",
"condition": "2",
"values": [
"ABC",
"XYZ"
]
}
],
"onlyMerge": "true",
"mergeBy": [
]
}
And I am using these classes
public class Outermost{
public string user;
public Root filter ;
public string onlyMerge;
public string mergeby;
}
public class values {
public string value { get; set; }
}
public class Filters {
public string filtername {get; set; }
public string condition {get; set;}
public values values { get; set; }
}
public class Root {
public List<Filters> Filters { get; set; }
}
JSONConvert.Deserialize(Outermost)
I have to deserialize the structure
Paste your JSON into http://json2csharp.com/ and you will see that your C# classes don't match the JSON.
Update 2:
Visual Studio 2013 has a built-in Json to C# Class converter tool!  :)
Update:
Just a note about the great tool http://json2csharp.com/ : When working with a object that has properties of complex types, You may want to check about the classes it creates, because sometimes it'll created unnecessarily/undesirable classes. Example:
Json
var objJson = {
"id_product": 19,
"description": "Laptop",
"_links": {
"buy": {
"href": "/Product/Buy/19",
"title": "Buy It Now!"
},
"more_details": {
"href": "/Product/Details/19",
"title": "More Details..."
}
}
};
Generated Class/Classes:
public class Buy
{
public string href { get; set; }
public string title { get; set; }
}
public class MoreDetails
{
public string href { get; set; }
public string title { get; set; }
}
public class Links
{
public Buy buy { get; set; }
public MoreDetails more_details { get; set; }
}
public class RootObject
{
public int id_product { get; set; }
public string description { get; set; }
public Links _links { get; set; }
}
As You can see, the two classes Buy and MoreDetails have exactly the same structure and purpose, so You may want to replace it with a more generic class instead of using repeatedly classes (there are scenarios where this redundant structure is more appropriate). In a very similar scenario, I've created a class named Link.
Original Answer:
You don't said enough to be sure what's your problem. Try in the future specify better what are your difficulties and needs.
But, I guess your problem is some exception being throw or some properties not being bind...
If you pay attention, in your JSON example object, filter is directly a collection, and not a property that has a collection inside. Thus, just change
public Root filter; to public List<Filters> filter { get; set; }.
Also, mergeBy and values are collections, and not simple strings. You could use http://json2csharp.com/ to generate automatically the correspondent C# class of your JSON object, and check what properties are not matching... (Or, substitute your whole class, that is what I would recommend...)

Order of properties get messed up when serialized by JSON.NET

In my POCO objects, I often inherit from other POCO objects. When I serialize a POCO object using JSON.NET, the order of properties gets all messed up.
Say, I have a Person class that looks like this:
public class Person
{
public int Id {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
Then I have an Employee class that inherits from Person class:
public class Employee : Person
{
public int DepartmentId {get; set;}
public string Title {get; set;}
}
When I serialize the Employee class, my JSON object looks like this:
{
"departmentId": 123,
"title": "Manager",
"id": 1234567,
"firstName": "John",
"lastName": "Smith"
}
Two questions:
Does the order of my JSON object properties matter?
Even if the order of properties doesn't matter, how can I get the properties to be in correct order i.e. I'd like to see the Person class properties first, then the Employee class properties.
Thank you for your help.
1.) No, order doesn't matter.
2.) You can use the [JsonProperty(Order=x)] attribute to control the order:
public class Employee : Person
{
[JsonProperty(Order = 1)]
public int DepartmentId { get; set; }
[JsonProperty(Order = 1)]
public string Title { get; set; }
}
From a quick test, order defaults to 0, is sorted from low to high, and properties with the same value of Order are sorted in an arbitrary order.
Actually, since my Object was already a JObject, I Had to use the following solution:
public class SortedJObject : JObject
{
public SortedJObject(JObject other)
{
var pairs = new List<KeyValuePair<string, JToken>>();
foreach (var pair in other)
{
pairs.Add(pair);
}
pairs.OrderBy(p => p.Key).ForEach(pair => this[pair.Key] = pair.Value);
}
}
and then use it like this:
string serializedObj = JsonConvert.SerializeObject(new SortedJObject(dataObject));

Categories

Resources