Jimenemex
Jimenemex

Reputation: 3176

Deserialize JSON into any object

I have an API request that goes off and the response structure back looks like this:

{
    "MessageBody": {
        "foo" : ""
    }
}

The properties under MessageBody can be anything, not only foo, but its value is always a string.

eg. {"MessageBody": { "Token": "abc" }} or {"MessageBody": { "Name": "abc" }}

How can I capture this response from the API as a generic object for the property under MessageBody?

I can represent the first example above as:

public class MessageBody
{
    public string Token { get; set; }
}

How would I represent both Token or Name properties under the same MessageBody object? There's a bunch of different values that MessageBody can have, but again they would all be of type string.

Upvotes: 2

Views: 661

Answers (1)

Alex
Alex

Reputation: 519

I have acheived something similar using Newtonsoft

Your route should take the body in as a generic object and it can then be deserialized into any object you'd like:

/*Using this method, the controller will automatically handle
validating proper Json format*/
[HttpPost]
public async Task<IActionResult> Post([FromBody] object Body)
{
     
    /*here you will send the generic object to a service which will deserialize.
    the object into an expected model.*/
       
    customService.HandlePost(Body);
}

Now create an object with any expected fields you would get from the body. (Json2csharp.com is extremely useful!)

public class MessageBody    
{
    public string Token { get; set; } 
    public string Name { get; set; } 

}

Inside your service you can handle the object like this:

using Newtonsoft.Json
using Models.MessageBody

public class customService()
{
    
   public void HandlePost(object body)
   {
      
       var DeserializedBody = JsonConvert.DeserializeObject<MessageBody>(body);

       //Any Values that were not assigned will be null in the deserialized object
       if(DeserializedBody.Name !== null)
       {
          //do something
       }
    
   }

}

This is obviously a very bare bones implementation, error handling will be important to catch any invalid data. Instead of using one object and null fields to get the data you need, I would recommend adding a "subject" route variable (string) that you can use to determine which object to deserialize the body into.

post *api/MessageBody/{Subject}

Upvotes: 2

Related Questions