2

I'm currently working on a .NET Framework 4.7.2 application. I'm retrieving data from a Web API as a JSON string result, I need to convert the result into an IEnumerable or IList of ExpandoObject.

my JSON can have dynamic properties and looks like this:

{ "data" : [
   {"Id":1, Text:"Test1", coolProp: 213 },
   {"Id":2, Text:"Test2"},
   {"Id":3, Text:"Test3", otherProp: "cool" },
]}

I need to select the JSON objects, without the key "data" and return a dynamic List of ExpandoObjects.

My current C# looks like this:

var json = JsonConvert.DeserializeObject<ExpandoObject>(await response.Content.ReadAsStringAsync());
var result = json.FirstOrDefault(x => x.Key == "data").Value;

This works fine, but the result is just a simple object containing several ExpandoObjects.

I can not cast the result, neither implicitly nor explicitly, to a List<ExpandoObject>.

When I try to return result, the Error message is the following:

Cannot implicitly convert type 'object' to List.

When I try to cast explicitly, result is null:

var result= json.FirstOrDefault(x => x.Key == "data").Value as List<IDictionary<int, ExpandoObject>>;

The result without cast looks like that in the immediate window:

result
Count = 7
    [0]: {System.Dynamic.ExpandoObject}
    [1]: {System.Dynamic.ExpandoObject}
    [2]: {System.Dynamic.ExpandoObject}
    [3]: {System.Dynamic.ExpandoObject}
    [4]: {System.Dynamic.ExpandoObject}
    [5]: {System.Dynamic.ExpandoObject}
    [6]: {System.Dynamic.ExpandoObject}

Do you know how to solve this issue? Or perhaps, do you know a better approach? I don't want to return the key "data" in my result, just a simple list of dynamic objects.

Thank you!!

timhorton42
  • 241
  • 5
  • 15

2 Answers2

3

You can try parsing json and extract exactly what you need. I assume you are going to target data within the root element but not the data itself.

So you go ahead with

JObject.Parse(myJson)["data"]

Also, If you want a result to be a list then deserialize it as List<ExpandObject> not ExpandObject.

Here is the fully working demo that you can test on your local -

 internal class ExpandObject
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public string coolProp { get; set; }
        public string otherProp { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            String text = "{\"data\":[{\"Id\":1,\"Text\":\"Test1\",\"coolProp\":213},{\"Id\":2,\"Text\":\"Test2\"},{\"Id\":3,\"Text\":\"Test3\",\"otherProp\":\"cool\"}]}";
            var deserialized = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ExpandObject>>(Convert.ToString(JObject.Parse(text)["data"]));
            Console.ReadLine();
        }
    }
Manoz
  • 6,507
  • 13
  • 68
  • 114
1

I think I found the solution of your problem.The problem i get was that once you get the first key it interprets it as an object not as an expandoObject. But since you want a dictionary you can cast it inside the dictionary function of the key.

var json = JsonConvert.DeserializeObject<ExpandoObject>(jsonData);
var result = json.FirstOrDefault(x => x.Key == "data").Value;
var items = ((IEnumerable<Object>)json.FirstOrDefault(x => x.Key == "data").Value).ToDictionary(x => ((ExpandoObject)x).FirstOrDefault(y=>y.Key == "Id").Value, x=>x);`

If you need that the resultant dictionary to be Dictionary<int,expandoObject> you can replace the last line for this:

Dictionary<int, ExpandoObject> items = ((IEnumerable<Object>)json.FirstOrDefault(x => x.Key == "data").Value).ToDictionary(x => int.Parse(((ExpandoObject)x).FirstOrDefault(y=>y.Key == "Id").Value.ToString()), x=>(ExpandoObject)x);`

Hope it is what you need.

d219
  • 2,707
  • 5
  • 31
  • 36
AlbertoCh
  • 120
  • 2
  • 6