FlyingFree
FlyingFree

Reputation: 21

Iterating through dictionary object value which is a list

I'm trying to get a list of users and phones from DUO using the DUO_Admin api. Response from DUO gives an array of dictionary items. Most items in the dictionary are like:

"firstname": "Joe",
 "email": "[email protected]",
 "phones": [{
             "phone_id": "DPFZRS9FB0D46QFTM899",
             "number": "+15555550100"
           }]

But there are some items where the value of the dictionary item are lists themselves as shown by PHONES above.

            var client = new DuoApi(ikey, skey, host);
            var parameters = new Dictionary<string, string>();

            // /admin/v1/users returns a JSON Array instead of an object.
            System.IO.StreamWriter file = new System.IO.StreamWriter(usersFilePath);

            var users = client.JSONApiCall<System.Collections.ArrayList>(
                            "GET", "/admin/v1/users", parameters);

            foreach (Dictionary<string, object> user in users)
            {
                    file.WriteLine((user["username"] as string + "," +
                    user["created"] + "," +
                    user["email"] + "," +
                    user["firstname"] + "," +
                    user["lastname"] + "," +
                    //user["phones"] + "," +  //THIS IS A LIST OF PHONES
                    user["user_id"]));

                   ''THIS IS THE CODE I CAN"T GET TO WORK
                   foreach (Dictionary<string, object> phone in user["phones"] as Dictionary<string, object>)
                    {
                        MessageBox.Show("" + phone["name"]);
                        MessageBox.Show("" + phone["phone_id"]);
                    }
            }

I'm having issues retrieving these inner items as shown in the code above. I can get email, firstname etc but can't retrieve the phone items.

Upvotes: 1

Views: 93

Answers (2)

FlyingFree
FlyingFree

Reputation: 21

thanks for your reply tymtam.

Your IEnumerable suggestion worked and I have the following working to give me those inner phone details.

     foreach (Dictionary<string, object> uPhone in user["phones"] as IEnumerable)
                {                   
                    filePhones.WriteLine((uPhone["name"] as string + "," +
                       uPhone["activated"] + "," + uPhone["type"]));
                }

Thanks again!

Upvotes: 0

tmaj
tmaj

Reputation: 34947

I'm not sure what JSONApiCall does, but what if you obtain the json and instead of using it as a Dictionary<string, object> you either:

  • (preferred) deserialise it to a concrete model; or
  • deserialise it to a JObject (or even dynamic, but don't).

You can use Json.NET or in .NET Core System.Text.Json.

Here's an example from Json.NET.

string json = @"{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': [
    'Action',
    'Comedy'
  ]
}";

Movie m = JsonConvert.DeserializeObject<Movie>(json);

string name = m.Name;
// Bad Boys

With the new .NET Core JsonSerializer it would look something like the following.

string json = ... ;

var movie = System.Text.Json.JsonSerializer.Deserialize<Movie>(json);

string name = m.Name;

I still want to use Dictionary<string, object>

Again, I don't know what JSONApiCall does to arrays and nested objects.

If you structure the code sligthly differently it could help you debug it easier.

Consider the following snippet.

//Put a breakpoint here and examine the type of phones;
var phonesO = user["phones"];
var phones = phonesO as IEnumerable; // This may or may not work
if (enumerable == null)
{
   // Nope, something is not right
}
foreach (var phoneO in phones)
{
    //Put a breakpoint here and examine the type of `phoneO`
    var phone = phoneO as Dictionary<string, object>();
    {
        var number = phone["number"];
        var phoneId = phone["phone_id"];
    }
}

Upvotes: 1

Related Questions