Home > Software engineering >  Deserialising a JSON response from a httpclient Post request into a custom object
Deserialising a JSON response from a httpclient Post request into a custom object

Time:08-16

I want to call a httpClient Post method and put the JSON response, which is an array consisting 2 double and put them as respective field in an object. e.g. the response is:

[12345, 56789] 

I want to put 12345 as newObject.firstPrice, and 56789 as newObject.secondPrice, and retrieve them to do some computation later on. However, I am not sure how to do it.

I have seen 2 ways of deserialising a JSON response on the internet.

1st example:

seems like I should create a newObject and use <IEnumerable<newObject>> & for each to do so? But what should I put inside the {} in for each?

namespace ConsoleProgram
{
    public class DataObject
    {
        public string Name { get; set; }
    }

    public class Class1
    {
        static void Main(string[] args)
        {
            // HTTP request goes here
            
            if (response.IsSuccessStatusCode)
            {
                // **Deserialisation into the Dataobject?**
                var dataObjects = response.Content.ReadAsAsync<IEnumerable<DataObject>>().Result;  
                foreach (var d in dataObjects)
                {
                    Console.WriteLine("{0}", d.Name);
                }
            }
               ...

2nd example:

(taken from the question ReadAsAsync deserializing HttpResponseMessage result)

PI caseInfos = null;
try
{
    string strasd = response.Content.ReadAsStringAsync().Result;
    m_Logging.Log(SharedLib.LoggingMode.Prompt, "ReadAsStringAsync() result:{0}", strasd);
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(PI));
    using (TextReader reader = new StringReader(strasd))
        caseInfos = (PI)serializer.Deserialize(reader);
    m_Logging.Log(SharedLib.LoggingMode.Prompt, "Deserializing caseInfos model succeeded...");
}
catch (Exception ex)
{
    m_Logging.Log(SharedLib.LoggingMode.Error, "creating model failed, EXP:{0}", ex);
}

The 2nd way seems more complicated, may I ask is it even the correct way to go for?

CodePudding user response:

could be

if (response.IsSuccessStatusCode)
{
    var  json = response.Content.ReadAsStringAsync().Result;

    List<double> data = JsonConvert.DeserializeObject<List<double>>(json); 

     // or 
     double[] data = JsonConvert.DeserializeObject<double[]>(json); 

    var firstPrice= data[0];
}

CodePudding user response:

Serge's answer works, but if you wanted to specifically convert those values into a object with FirstPrice and SecondPrice properties, you could deserialize to an IList<double> and then create an object from the deserialized value (This assumes that you are getting exactly 2 double values back. You might need to do additional checks in any other situation)

public class Result
{
    public Result()
    {
    }

    public Result(double firstPrice, double secondPrice)
    {
        this.FirstPrice = firstPrice;
        this.SecondPrice = secondPrice;
    }

    public double FirstPrice { get; set; }

    public double SecondPrice { get; set; }

    public static Result FromResponse(IList<double> values)
    {
        ArgumentNullException.ThrowIfNull(values);

        return values.Count == 2
            ? new Result(values[0], values[1])
            : throw new ArgumentException(nameof(values), "Expected 2 double values");
    }

    public override string ToString()
    {
        return $"{nameof(FirstPrice)}: {this.FirstPrice}, {nameof(SecondPrice)}: {this.SecondPrice}";
    }
}

Then when you're handling the HttpResponseMessage, you can pass the content to the static method.

if (response.IsSuccessStatusCode)
{
    var responseContent = await response.Content.ReadAsStringAsync();
    var content = JsonSerializer.Deserialize<IList<double>>(responseContent);
    var result = Result.FromResponse(content);
}
  • Related