Dany G
Dany G

Reputation: 345

Parsing Json .Net Web Api

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:

  1. Any idea of the POCO or class that match this kind of json. ("rule" list It's variable, can be one or more).

  2. After create this poco or class I would have to make a controller based on this?

Upvotes: 1

Views: 14481

Answers (4)

Julius
Julius

Reputation: 29

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;
    }
}

Upvotes: 1

Lukazoid
Lukazoid

Reputation: 19416

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

Upvotes: 4

Vyrira
Vyrira

Reputation: 174

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.

Upvotes: 0

Dan Forbes
Dan Forbes

Reputation: 2824

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.

Upvotes: 1

Related Questions