TechnoSavvy
TechnoSavvy

Reputation: 107

How to store API result set for different response types using C#.Net

I am trying to call two API's and store their response. Below is the API response type:

API1 response:

{
  "Name": "Apple",
  "Expiry": "2008-12-28T00:00:00",
 "Price": 3.99,
 "Sizes": [
 "Small",
 "Medium",
 "Large"
  ]
}

API2 Response:

["Name=xyz, Id=1, Version=1","Name=abc, Id=1, Version=2","Name=hgf, Id=1, Version=3","Name=utgds, Id=1, Version=4","Name=kfgf, Id=2, Version=1"]

below is the code to call an API and get the result set.

var jsonObj = Get<SomeClass>("API_URL1");
var jsonObj2 = Get<Test>("API_URL2");

 public T Get<T>(string requestUri)
        {
            T response = default(T);
            using (var handler = new HttpClientHandler { Credentials = CredentialCache.DefaultNetworkCredentials })
            {
                using (var httpClient = CreateNewRequest(handler))
                {
                    var httpTask = httpClient.GetAsync(requestUri);
                    var response = task.Result;
                    response.EnsureSuccessStatusCode();
                    if (response.IsSuccessStatusCode)
                    {
                        var result = response.Content.ReadAsStringAsync().Result;
                        var res = JsonConvert.DeserializeObject<T>(result);

                    }
                }
            }
            return res;
        }

 private HttpClient CreateNewRequest(HttpClientHandler handler)
    {
        HttpClient client = new HttpClient(handler);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        return client;
    }

public class Test
{
    public string Name { get; set; }
    public int Id { get; set; }
    public int Version { get; set; }


}

Similarly i have created a class to hold the API1 response. I am able to store API1 Response however while storing API2 response i am getting this error message.

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface..

any idea/hints on this?

Thanks!

Upvotes: 2

Views: 3156

Answers (1)

Paweł Dyl
Paweł Dyl

Reputation: 9143

I tested what i said in comment. Second response is JSON array of strings. You should deserialize it as array of string (string[]) or collection of strings (List<string>). Following works as expected:

var response = "[\"Name=xyz, Id=1, Version=1\", \"Name=abc, Id=1, Version=2\", \"Name=hgf, Id=1, Version=3\", \"Name=utgds, Id=1, Version=4\", \"Name=kfgf, Id=2, Version=1\"]";
var result = JsonConvert.DeserializeObject<string[]>(response);

To summarise: instead of Get<Test> use Get<string[]>. You just have to parse strings, but this seems to be another problem.


Full demo below (url invocations intentionally mocked):

class Program
{
    static void Main(string[] args)
    {
        var invoker = new JsonMockInvoker();
        var jsonObj = invoker.Get<SomeClass>("API_URL1");
        var jsonObj2 = invoker.Get<string[]>("API_URL2");
    }
}

class SomeClass
{
    public string Name { get; set; }
    //other properties
}

public class JsonMockInvoker:JsonInvoker
{
    public override string InvokeRest(string url)
    {
        if (url == "API_URL1")
            return "{\"Name\": \"Apple\",\"Expiry\": \"2008-12-28T00:00:00\",\"Price\": 3.99,\"Sizes\": [\"Small\",\"Medium\",\"Large\"]}";
        if (url == "API_URL2")
            return "[\"Name=xyz, Id=1, Version=1\", \"Name=abc, Id=1, Version=2\", \"Name=hgf, Id=1, Version=3\", \"Name=utgds, Id=1, Version=4\", \"Name=kfgf, Id=2, Version=1\"]";
        throw new NotImplementedException();
    }
}

public class JsonInvoker
{
    public T Get<T>(string requestUri)
    {
        var result = InvokeRest(requestUri);
        return result != null ? JsonConvert.DeserializeObject<T>(result) : default(T);
    }

    public virtual string InvokeRest(string url)
    {
        using (var handler = new HttpClientHandler { Credentials = CredentialCache.DefaultNetworkCredentials })
        using (var httpClient = CreateNewRequest(handler))
        {
            var httpTask = httpClient.GetAsync(url);
            var response = httpTask.Result;
            response.EnsureSuccessStatusCode();
            if (response.IsSuccessStatusCode)
            {
                return response.Content.ReadAsStringAsync().Result;
            }
        }
        return null;
    }

    private HttpClient CreateNewRequest(HttpClientHandler handler)
    {
        HttpClient client = new HttpClient(handler);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        return client;
    }
}

String values are not in JSON format - you have to parse them manually:

//parse to typed object
var parsedObject = jsonObj2.Select(a => new
{
    Id = Regex.Match(a, "(?<=Id=)[^,]*").Value,
    Name = Regex.Match(a, "(?<=Name=)[^,]*").Value
});

//parse to dictionary
var regex = new Regex("([\\s]|^)(?<key>[^=]+)=(?<value>[^,]*)");
var parsed = jsonObj2.Select(a =>
{
    var dictionary = new Dictionary<string, string>();
    foreach (Match match in regex.Matches(a))
        dictionary[match.Groups["key"].Value] = match.Groups["value"].Value;
    return dictionary;
});

Upvotes: 2

Related Questions