Parsing Json .Net Web Api - c#

I'm new with Web API 2 / Entity Framework 6 project, I'm making REST services, but for one specific service I'm going to receive (via Post) a JSON before making any CRUD operations over any entity of the model, (have to make some business validations over the data, add or complement some things and decide on wich entity to save), the JSON is:
{
"head": {
"action": "create",
"object": "oneobject",
"user": "theuser"
},
"object": {
"name1": "a name 1",
"name2": "a name 2",
"description": "a description here"
},
"rule": [{
"name": "any name",
"value": "any value"
}, {
"name": "another name",
"value": "another value"
}]
}
So the json not maps directly to an entity, in fact I have no model or object for this. What would be the better way to work with it? I mean how to receive and parse the json. I'm new with web api and rest services, and I would appreciate you can help me and explain me with good details. Thanks guys.
Edit:
Any idea of the POCO or class that match this kind of json. ("rule" list It's variable, can be one or more).
After create this poco or class I would have to make a controller based on this?

As others have said, what you need is a POCO object to represent your request. Based on the information you have provided the following should achieve close enough to what you are after:
public enum CrudAction
{
Create,
Read,
Update,
Delete
}
public sealed class CrudRequestHeader
{
public CrudAction Action { get; set; }
public string Object { get; set; }
public string User { get; set; }
}
public sealed class RuleDefinition
{
public string Name { get; set; }
public string Value { get; set; }
}
public sealed class CrudRequest
{
public CrudRequestHeader Head { get; set;}
public Dictionary<string, string> Object { get; set; }
public List<RuleDefinition> Rule { get; set; }
}
In your Web API controller method you can then take a parameter of type CrudRequest and your JSON will be deserialized to this object, e.g:
public IHttpActionResult Post(CrudRequest crudRequest)
{
// TODO Implementation
}
You may notice I have used Dictionary<string, string> for CrudRequest.Object as it is variable how many key/values we will be supplied with, I have made the assumption that all values are strings, you can use an object value if you prefer but you will then need to handle the type of value. In the same principle I have used List<RuleDefinition> for CrudRequest.Rule to cater for the variable number of rules which may be supplied.
A LINQPad sample containing the above definitions and use with your input can be found here: http://share.linqpad.net/7rvmhh.linq

Although the JSON may not represent a logical entity in your model, you clearly have a mental model of the "shape" of the JSON data - I say this because you define it in your code snippet. You should create a POCO (plain old C# object) to represent this model, and deserialize the incoming JSON request to an object of that type. Once you've deserialized it to your object, it will be trivial to work with this data using object properties and such.

The best thing to do would be to create a class that models the object you expect back.
This way in your Web API method you can use the [FromBody] attribute to automatically parse the body of the request.
Example -
Your data contract would look like this:
public class MyContract
{
public string MyData { get; set;}
}
In your ApiController
[HttpPost]
[Route("api/myobject")]
public async Task ReceiveMyObject([FromBody]MyContract object) {
var data = object.MyData;
// Do whatever you need to do here.
}
This may seem tedious but this will let you keep your code organized.
Edit
So to create a contract out of this:
{
"head": {
"action": "create",
"object": "oneobject",
"user": "theuser"
},
"object": {
"name1": "a name 1",
"name2": "a name 2",
"description": "a description here"
},
"rule": [{
"name": "any name",
"value": "any value"
}, {
"name": "another name",
"value": "another value"
}]
}
You would do something like this:
public class MyContract
{
[JsonProperty("head")]
public MetaObject Head
{
get; set;
}
// Not sure if this will work, but it probably will
[JsonProperty("object")]
public JObject ExtendedInformation
{
get;
set;
}
[JsonProperty("rule")]
public Rule[] Rules
{
get;
set;
}
}
// "MetaObject" definition omitted but you can understand my point with the below
public class Rule
{
[JsonProperty("name")]
public string Name
{
get;
set;
}
[JsonProperty("value")]
public string Value
{
get;
set;
}
}

Usually a REST service issue a contract, which means some kind of metadata to describe the content of its messages, otherwise you cannot call this as a RESTful Web API. Take a look at this post from Roy Fielding, who created the term of REST API, if you want to know better what is REST and what is not.
So if your service is a true REST service you should be able to have a description somewhere that give you the possibility to parse the media.
However, if you still cannot find any way to understand how the JSON should be interpreted you may be able to use it inside a C# class anyway: take a look at the JObject class from Newtonsoft.Json that enables to use a dynamic object at runtime.
Basically, it is used like this:
using Newtonsoft.Json.Linq; // This needs the Newtonsoft.Json package
dynamic entity = JObject.Parse(jsonString);
string value = entity.key1;
string value2 = entity["key2"];
I did this simple demo with your data.
You can also check the full documentation of the class on the Newtonsoft website.

Related

.Net Core CSharp Custom Json Deserialization

How can i perform custom deserialization of this object in .Net Core C#, that Afpak is assigned as 'string name' in this object class. I have the following JSon Code of the object:
{
"Afpak": {
"id": 1,
"race": "hybrid",
"flavors": [
"Earthy",
"Chemical",
"Pine"
],
"effects": {
"positive": [
"Relaxed",
"Hungry",
"Happy",
"Sleepy"
],
"negative": [
"Dizzy"
],
"medical": [
"Depression",
"Insomnia",
"Pain",
"Stress",
"Lack of Appetite"
]
}
}
EDIT: Note the object class is Strain, it gets variable name from root of this json - in this case the name variable would be Afpak, there is 100s of different Strain class objects in this one JSON code is what I am having trouble with as it doesnt make sense to create each one as seperate class if it is all of the same class.
you should implement a class exposing the properties you want to map from that JSON object.
Something like this:
public class AfpakDto{
public string id {get;set;}
public string race {get;set;}
public string[] flavors {get;set;}
}
public class FooDto {
public AfpakDto Afpak {get; set;}
}
and then use whatever library you want. Here's a nice article about System.Text.JSON: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?pivots=dotnet-5-0

How can I include an object and an integer in a JSON request?

I am creating an object called course. The function that creates the object requires another object and an integer to be passed through the HTTP request body. To include just the object, I simply did:
{
"courseName" : "sample course"
}
Now, I need to not only include the object but also an integer. This integer is not part of the course object, but I need it to be passed with the object in the same request. I want to do something like:
{
"course" : { "courseName" : "sample course" },
"ownerAccId" : 0000000
}
However, this does not work. It tells me no courseName was provided.
How can I include the object in a format where I can use it as the intended object and also include data outside the object?
design your C# model according to json.
public class Course {
public string courseName { get; set; }
}
public class Root {
public Course course { get; set; }
public int ownerAccId { get; set; }
}
It's hard to help without more information on what you're doing but maybe this might help
But let's say I were trying to write an API that would allow a consumer to create a new course that contained modules where I have Course and Module entities in my DB... I might write a JSON that looks something like this
{
"CourseID": "ComputerScience",
"CourseType": "Bachelor of Science",
"Modules": [{
"ModuleId": CS001,
"ModuleName": "Networking 101,
"Credits": 5,
},
{
"ModuleId": CS002,
"ModuleName": "Databases 101",
"Credits": 5,
}],
}
Under the hood, I'd have a database with tables. These would be represented in my code as entities.
Then I'd have consumer facing models (called DTOs) that I use to parse the requests from the consumer of the API.
Here, what I'm doing is creating a semantic structure for what I am expecting the JSON coming in to me to look like.
And that structure isn't a reflection of what's in the underlying tables. It's just a reflection of what a consumer needs to tell me about an entity and its relationships to other entities to be able to represent it in my application.
The kind of model I might use to interact with a request like the one above would be
public class Course
{
[Key]
public string CourseId { get; set; }
[Required]
[MaxLength(150)]
public string CourseType{ get; set; }
...
//This is how our model would be set up to handle a collection of (i.e. many) modules
public ICollection<Module> Modules { get; set; }
= new List<Module>();
..
}
I might imagine for the above example that the underlying DB might have a Course table and a Module table and the two might be linked under the hood using a 1:N relationship.
But I can't "know" that from looking at the JSON.
Suppose I wanted to also track Faculties so I'd know which faculties manage which courses.
Then I'd have to make changes to the database itself.
I might add a Faculty entity to the database and then I might put a FacultyID foreign key in my Coure table.
This way many courses can be owned by one faculty but each course can only be managed by one faculty
But I'd also have to make changes to the consumer facing model that I use to create new courses.
I'd also have to capture information on the faculty when a consumer tries to create a new course.
So the model that I might use here to interpret the JSON might look like this
public class Course
{
[Key]
public string CourseId { get; set; }
[Required]
[MaxLength(150)]
public string Type{ get; set; }
...
//This is our foreign key
//[ForeignKey("FacultyId")]
public string FacultyId { get; set; }
//This is how our model would be set up to handle a collection of (i.e. many) modules
public ICollection<Module> Modules { get; set; }
= new List<Module>();
..
}
And then with that model I would be able to handle a request like this
{
"FacultyId: "Science and Engineering",
"CourseID": "ComputerScience",
"CourseType": "Bachelor of Science",
"Modules": [{
"ModuleId": CS001,
"ModuleName": "Networking 101,
"Credits": 5,
},
{
"ModuleId": CS002,
"ModuleName": "Databases 101",
"Credits": 5,
}],
}
But for all this to work I'd have to handle the mapping between the consumer facing model and the db entities as well
So at the very least I hope this helps you understand the information you need to give us for us to be able to help you. We need information on the request, the models, the entities and the mapping between the entities and the models
You don't need to nested your model. you can pass both of them in a json format like below
{
"courseName" : "sample course",
"ownerAccId" : 0000000
}
More important, you have to generate your json according to their model, I mean if their model is not nested you don't need to make your json to be nested.
If you are using .Net framework, you can use Newton.Soft to serialize your model to json format.

Get specific json elements

I couln't find a similar case here, hence my question. I have a json like this:
{
"prop1": "bla",
"propn": "bla",
"Data": {
"42": {
"prop1": "bla",
"prop2": "bla",
"Symbol": "42"
},
"abc": {
"prop1": "bla",
"prop2": "bla",
"Symbol": "abc"
}
},
"Type": 100
}
Now, how do I get all elements from Data, and the most I am interested in the ones that have the symbol property set. I tried Newtonsoft.json.linq and jobject, but got really no clue what to do here. Any guidance anyone? Thanks!
Ronald
What you're looking for is called 'deserialize'. You have a string (the json in you post) and you want to turn it into an object.
The first steps you need to do are:
Create a class that matches your data.
Simply copy your json string in your post and use the option in Visual Studio to 'paste JSON as class'. Perhaps clean it up by changing the name RootObject to something more descriptive.
Install the NuGet package Newtonsoft in Visual Studio.
Now you can use MyClass myObject = JsonConvert.DeserializeObject<MyClass>(myString);
To access Symboljust use myObject.Data.Symbol
I imagine that once you extract partial data from json, if you still need to pass the data through your application, a dedicated model will come handy.
public class Data
{
public Element abc { get; set; }
}
public class Element
{
public string prop1 { get; set; }
public string prop2 { get; set; }
public string Symbol { get; set; }
}
While you certainly can rely on JObject handling the deserialization, i find it more intuitive to work with anonymous templates, especially for partial data retrieval.
var template = new
{
Data = default(Data)
};
var instance = JsonConvert.DeserializeAnonymousType(json, template);
will give you something like
I recomend you to use Jil library, is faster and more simple than Newtonsoft.json

what is the best way to only retrieve certain values from a json string

I am attempting to use the API from a 3rd party website to retrieve information, unfortunately it provides way more information that I need. from my understanding of the java deserializer, the class needs to exactly match the json string to parse properly. I was wondering if there was a way to retrieve only the values I am interested in without having to do a ton of string splitting.
example:
//my class
class message
{
public string id { get; set; }
public string author { get; set; }
public string body { get; set; }
}
// json string
{
"body": "this is test 2",
"was_comment": false,
"first_message": null,
"name": "name",
"first_message_name": null,
"created": 1402707862.0,
"dest": "recipiant",
"author": "author",
"parent_id": null,
"context": "",
"replies": "",
"new": true,
"id": "das9deh",
"subject": "test2"
}
as you can see there is a substantial amount of information in the json string that I do not need for my purposes, so I was wondering if there is an efficient way to simply pull out the id,author, and body values directly to my class.
This is why my question is different:
I get a large json string from a 3rd party that I want to deserialize. my question is, how to deserialize without having a class that exactly matches the json string as I only need selected values.
in the proposed solution is the opposite of the answer I'm looking for

Alter Json or ExtensionDataObject

I have a Json service I cannot alter as it is not mine.
Their Json is a formatted in a way that parsing it is difficult. It looks something like this.
"people": {
"Joe Bob": {
"name": "Joe Bob",
"id": "12345"
},
"Bob Smith": {
"name": "Bob Smith",
"id": "54321"
}
},
I would really prefer this was laid out like a JSon array, however it presently is not.
I am wondering the best approach here. Should I alter the Json to look like an array before I parse it or load up the ExtensionData and parse it from that?
There are other items in the feed that I do not have issue with. Just stuck with this one section.
Thanks
You can use json.net to deserialize the data (the json you pasted, and doing only one parsing, without modifying anything).
using dynamic foo = JsonConvert.DeserializeObject<dynamic>(data)
than, you can iterate the list using foo.people, accessing the Name and Value.
you can create a class (if you know what the schema is, and to deserialize the data into a list of the given class such as:
public class People
{
[JsonProperty(PropertyName="people")]
public IDictionary<string, Person> Persons { get; set; }
}
public class Person
{
[JsonProperty(PropertyName="name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
}
and than call:
var obj = JsonConvert.DeserializeObject<People>(data);
foreach (var item in obj.Persons.Values)
{
//item is instance of Person
}
Another good and possible option will be:
How can I navigate any JSON tree in c#?

Categories