championq45
championq45

Reputation: 263

Deserializing an API call response content without having to create a model representing the content

Is there another way to deserialize the response content of an API call into a generic object in .Net without having to create a model representing the JSON object? In other words, is there or does .Net provide a generic object or model that i can use to deserialize the response into. The reason being is because every API call response is not the same which means I have to create a new model for every API call, and I have about 20 different endpoints that return different responses, which means I would have to create 20 models representing the response.

Upvotes: 0

Views: 1588

Answers (4)

CajunCoding
CajunCoding

Reputation: 969

You may be looking for dynamic object which is late bound with unknown compile time properties.

A handy implementation of this is the JObject available with Newtonsoft.Json package and it offers similar functionality to the typeless elements of Javascript in that the properties can be of any type, with any nesting, etc. as long as it was parsed from well formed Json.

Usage is super simple, but watch out for null values, etc as default behavior for dynamic (aka ExpandoObject under the hood) is to throw exceptions for properties (aka Keys) not found...

    public static void Run()
    {
        string apiJsonResponse = @"{
            Name: 'Luke Skywalker',
            Title: 'Jedi',
            Skills : [
                'Lightsaber',
                'The Force'
            ]
        }";

        dynamic json = JObject.Parse(apiJsonResponse);
        Console.WriteLine($"Name: {json.Name}");
        Console.WriteLine($"Title: {json.Name}");
        Console.WriteLine($"Skills: {String.Join(", ", json.Skills)}");
    }

The result will be the Json dynamically parsed and rendered without any strongly typed model:

enter image description here

Upvotes: 1

wenming
wenming

Reputation: 71

in .Net 3.1 after version, can use using System.Text.Json

api response data

{
   "Status" : "0"
   "Data" : {
      "FirstName" : "firstName",
      "LastName" : "lastName"
   }
}

Response Model

public class ResponseModel
{
    public string Status { get; set; }

    public JsonElement Data { get; set; }
}

Deserialize

public void Deserialize()
{
    var jsonString = "{ \"Status\": \"0\", \"Data\": { \"FirstName\": \"firstName\", \"LastName\" : \"last_name\"} }";
    var response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
    //get first_name
    var firstName = response.Data.GetProperty("FirstName").GetString();
    Console.WriteLine(firstName);
}

Upvotes: 0

Dan Chase
Dan Chase

Reputation: 1042

My recommendation would be to create request and response models for this, even though it feels like extra work. This is because you'll need to eventually pass the parameters to functions in your business layer anyway, and you'll want to take advantage of the type safety without doing a bunch of Int32.TryParse's, which at that point, you're creating variables and doing extra work anyway. Actually, you're not going to be able to outrun the type safety the language not only provides, but generally requires. What I've done, is just copy/paste my DTO or EDMX table model into the new class, then decorate it. Pretty fast.

Upvotes: 1

Vivek
Vivek

Reputation: 104

You can use generic method to have list of JObject. Based on your need you can extract model from jobject.

private static async Task<List<JObject>> CallApi(Uri uri, HttpContent data = null, string headerKey = null, string headerKeyVal = null)
    {
        string res = string.Empty;
        try
        {
            var handler = new HttpClientHandler
            {
                //UseDefaultCredentials = true,

            };
            using var client = new HttpClient(handler);
            if (!string.IsNullOrWhiteSpace(headerKey))
                client.DefaultRequestHeaders.Add(headerKey, headerKeyVal);
            var post = await client.GetAsync(uri);
            //var post = await client.PostAsync(uri);
            if (post.StatusCode != HttpStatusCode.InternalServerError)
            {
                res = await post.Content.ReadAsStringAsync();
            }
            return JsonConvert.DeserializeObject<List<JObject>>(res);
        }
        catch (Exception ex)
        {

            throw ex;
        }

    }

Upvotes: 0

Related Questions