1

i'm trying to deserialize the following json:

{
"oxide":{
    "Al2O3":"0.3",
    "CaO":"0.3",
    "FeO":"0.3",
    "MgO":"0.3",
    "MnO":"0.3",
    "SiO2":"0.3"
},
"temperature": "1800"

}

When I convert in this way everthing works:

        Oxides oxides = new Oxides();
        string oxidequery = req.Query["oxide"];
        string temperature = req.Query["temperature"];

        string requestBody = new StreamReader(req.Body).ReadToEnd();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        oxide.Al2O3 = data?.oxide.Al2O3;
        oxide.CaO = data?.oxide.CaO;
        oxide.FeO = data?.oxide.FeO;
        oxide.MgO = data?.oxide.MgO;
        oxide.MnO = data?.oxide.MnO;
        oxide.SiO2 = data?.oxide.SiO2;
        double tempDouble = temperature ?? data?.temperature;

But when I doing this it not working:

        Oxides oxides = new Oxides();
        string oxidequery = req.Query["oxide"];
        string temperature = req.Query["temperature"];

        string requestBody = new StreamReader(req.Body).ReadToEnd();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        oxide = (Oxides)data?.oxide;
        double tempDouble = temperature ?? data?.temperature;

In the second aproach i get the error

Cannot convert type 'Newtonsoft.Json.Linq.JObject' to 'Oxides'.

What I'm missing? I already searched and found that I have to explicit convert data.oxide, but I'm already doing this.

  • try providing type to Deserialize = > JsonConvert.DeserializeObject(requestBody); Parsing partial object : https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm – Jophy job Mar 20 '18 at 15:13
  • When I did a similar approach I found that numeric choice when trying to assign to a class was often a float, rather than a decimal or long when I required it. If we can see your Oxide class that would help. – Greg Mar 20 '18 at 15:13
  • Duplicate or related: [Unable to cast object of type Newtonsoft.Json.Linq.JObject even though I am trying to cast to an object with matching properties](https://stackoverflow.com/a/48130933/3744182). – dbc Mar 20 '18 at 16:15

2 Answers2

2

Try this:

dynamic data = JsonConvert.DeserializeObject<dynamic>(requestBody);
oxide = ((JObject)data?.oxide).ToObject<Oxides>();
ThePerplexedOne
  • 2,920
  • 15
  • 30
0

I believe your issue is where you do the Stream to read into a dynamic. When I encountered a similar issue, I returned as an object.

    public object DownloadFromApi(string url)
    {
        if (WebRequest.Create(url) is HttpWebRequest request)
        {
            request.Method = "GET";
            request.ContentType = "application/json";

            try
            {
                using (Stream response = request.GetResponse().GetResponseStream())
                    if (response != null)
                        using (var reader = new StreamReader(response))
                            return JsonConvert.DeserializeObject(reader.ReadToEnd());
            }

            catch (HttpRequestException exception)
            {
                ApplicationProvider.Log.Error($"An unhandled HTTP error has occurred.{Environment.NewLine}{exception.Message}");
                throw new Exception(exception.Message);
            }
        }

        ApplicationProvider.Log.Error($"Web request failed due to null value. {url}");
        throw new Exception($"A null parameter or response has occurred for {url}");
    }

This conversion appeared to solve my issue with the object being incorrectly deserialized as incorrect types. So I was able to do the following to read into my object.

    private static IEnumerable<AssetDataModel> GetAllDataForAsset(AssetModel asset)
    {
        dynamic apiResponse = new ApiRequestUtility().DownloadFromApi(optiAssetDataWithinRangeUrl);
        for (var index = 0; index != apiResponse.Items.Count; index++)
            yield return new AssetDataModel
            {
                Id = apiResponse["Items"][index].id,
                ResourceId = apiResponse["Items"][index].value[0].resourceId,
                Timestamp = apiResponse["Items"][index].timeValue,
                Value = apiResponse["Items"][index].value[0].value
            };
    }

That allowed the correct conversion when I iterated through the response to build my data collection. So some of the odd trying to deserialize to float rather than decimal seemed to alleviate with our laboratory data.

Also would like to point out, return as an object but still have return type as dynamic to be determined at runtime.

Greg
  • 11,302
  • 2
  • 48
  • 79