1

I am trying to access a .json endpoint with this line of code inside Main():

var RM= ParseArrayFromWeb<RM>("http://myendpoint.json").ToArray();              

Here is the ParseArrayFromWeb function that is defined above/outside of MAIN()

public static IEnumerable<T> ParseArrayFromWeb<T>(string url)
{
    var webRequest = WebRequest.Create(url);
    using (var response = webRequest.GetResponse())
    {
        if (response != null)
        {
            var stream = response.GetResponseStream();
            if (stream != null)
            {
                using (var reader = new StreamReader(stream))
                {
                    return JsonConvert.DeserializeObject<IEnumerable<T>>(reader.ReadToEnd());
                }
            }
        }
        throw new WebException("Options request returned null response");
    }
}

Here is the RM class that is defined above/outside of Main() that should hold the json fields returned:

public class RM
{

    public string calculation_method { get; set; } 
    public double? related_master_id { get; set; }
    public string related_master_name { get; set; }
    public string parameter_file_date { get; set; } 
    public string exchange_complex { get; set; }
    public string combined_commodity_code { get; set; }
    public string currency { get; set; }
    public double? maintenance_margin { get; set; }
    public double? scanning_risk { get; set; }
    public double? spread_charge { get; set; }
    public double? spot_charge { get; set; }
    public double? inter_commodity_credit { get; set; }
    public double? short_option_minimum { get; set; }
    public double? scenario_number { get; set; }
    public double? initial_margin { get; set; }
    public string exchange_code { get; set; } 
    public string product_description { get; set; }
    public string error_description { get; set; }
}

The error I am getting is:

Cannot deserialize JSON object into type 'System.Collections.Generic.IEnumerable`1[JSON.Program+RM]'.

HERE is one row of the JSON:

{"error_description":"error 454", "combined_commodity_code":"xx", "exchange_complex":"x", "exchange_code":"x", "initial_margin":null, "maintenance_margin":null, "scanning_risk":null, "spread_charge":null, "spot_charge":null, "currency":null," inter_commodity_credit":0},

Notice not all fields are present. That is ok. I have to handle that.

Any ideas?

Thank you.

user3022875
  • 8,598
  • 26
  • 103
  • 167
  • 4
    How does the json look like? – Andrei Jan 27 '14 at 17:14
  • Shouldn't this `var RM= ParseArrayFromWeb("http://myendpoint.json").ToArray();` be this `var RM= ParseArrayFromWeb("http://myendpoint.json").ToArray();`?? – ichramm Jan 27 '14 at 17:17
  • The converter probably can't instantiate an IEnumarable. Try using or > as the generic parameter for DeserializeObject. Or try using a non-generic overload first and check in the debugger what it deserializes to. – Mark Jan 27 '14 at 17:19
  • @ichramm I had a type it should read RM – user3022875 Jan 27 '14 at 17:24
  • @Mark When I make the change you suggest I get this error: Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?) – user3022875 Jan 27 '14 at 17:25
  • I was too brief in my example. I meant: return (IEnumerable)JsonConvert.DeserializeObject(reader.ReadToEnd()) – Mark Jan 27 '14 at 17:27
  • @Mark I get this error with your most recent suggestion: Cannot deserialize JSON object into type 'JSON.Program+RM[]'. – user3022875 Jan 27 '14 at 17:31
  • possible duplicate of [Deserializing JSON Object Array with Json.net](http://stackoverflow.com/questions/18192357/deserializing-json-object-array-with-json-net) – Jamiec Jan 27 '14 at 17:35
  • @Andrei I have added an example JSON row. – user3022875 Jan 27 '14 at 17:38
  • Some of the fields in your example are null (such as maintenance_margin) and the class defines them as double which is not a nullable type. Maybe DeserializeObject expects nullable types? Try double? and see if it makes any difference. – PaulK Jan 27 '14 at 18:27

1 Answers1

3

The problem is with this instruction:

return JsonConvert.DeserializeObject<IEnumerable<T>>(reader.ReadToEnd());

You cannot deserialize to interfaces, since they cannot be instantiated, and the deserialization process, by nature, instantiate objects to store the data in the JSON. You need to use a concrete class for the deserialization, like this:

return JsonConvert.DeserializeObject<List<T>>(reader.ReadToEnd());

Hope this helps.

scubaFun
  • 1,269
  • 1
  • 15
  • 26
  • When I implement that I get this error: Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[JSON.Program+RelatedMasterRecord]'. – user3022875 Jan 27 '14 at 17:58
  • @emendezrivas What's the purpose of calling AsEnumerable when List already implements IEnumerable? – PaulK Jan 27 '14 at 18:23
  • @PaulK you are correct. I modified the answer to remove that part. – scubaFun Jan 27 '14 at 18:28
  • @user3022875 something that I was looking is that there are some NULLs in the JSON, when the RM class does not accept NULLS for the double fields. For example, the initial_margin field value on the JSON is null, but the field is double. This will raise an exception, because you cannot store null on a double field. If you want the fill to be able to store NULL values, you must declare it as double?. – scubaFun Jan 27 '14 at 18:31
  • @emendezrivas Using your latest code I get this error: Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[JSON.Program+RM]'. – user3022875 Jan 27 '14 at 18:41
  • @user3022875 did you check my latest comment regarding the NULL values? Here is the comment, for your convenience: "something that I was looking is that there are some NULLs in the JSON, when the RM class does not accept NULLS for the double fields. For example, the initial_margin field value on the JSON is null, but the field is double. This will raise an exception, because you cannot store null on a double field. If you want the fill to be able to store NULL values, you must declare it as double?" – scubaFun Jan 27 '14 at 19:44
  • @emendezrivas I changed the code. See above. I still get this error: Cannot deserialize JSON object into type 'System.Collections.Generic.IEnumerable`1[JSON.Program+RelatedMasterRecord]'. – user3022875 Jan 27 '14 at 19:51
  • @user3022875 that's strange, you see, I made a console application with the code and information that you provided, and it worked fine for me. Maybe how the JSON is received is what it is wrong, as others mentioned? Does the JSON received is similar to this one?: [ { "error_description":"error 454", "combined_commodity_code":"xx", "exchange_complex":"x", "exchange_code":"x", "initial_margin":null, "maintenance_margin":null, "scanning_risk":null, "spread_charge":null, "spot_charge":null, "currency":null, "inter_commodity_credit":0 } ] – scubaFun Jan 27 '14 at 20:25
  • @emendezrivas Yes that is an actual row of data. Notice some fields are missing. That is how the data is provided. Some fields will exist and sometimes others will not. Do I need to do anything special to handle the case when some fields are missing? Thank you. – user3022875 Jan 27 '14 at 20:31
  • @user3022875 as far as my tests tell, there is no need to add special logic to manage these cases, if and only if these fields on the model allows NULL values. – scubaFun Jan 27 '14 at 21:04