1

I have a json object that is coming from an endpoint.

{
"user_info": {
    "myapp1": {
      "roles": [
        "requestor"
      ]
    },
    "myapp2": {
      "roles": [
        "requests-edit",
        "requests-view"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  }
}

Based on this structure its pretty clear that there are two strongly typed objects. user_info and roles. However, the apps (myapp1, myapp2, account) are not in an array, they are "dynamic" or "anonymous" objects.

What is the recommended way to get the roles with a known app name?

EG, some pseudo code.

// returns the sub objects as a dictionary of <string, Roles>;
var anonjson = JsonAnon.DeserializeOnProperty<string, Roles>("user_info");
var roles = anonjson.Where(x => x.Key.Value == "myapp2").FirstOrDefault();
// i forget what dictionaries use to get by key I put x.Key, this could be invalid.
1
  • Have you considered converting the JSON into an Xml document and then use an xpath query? See How To Convert Json To Xml Commented Oct 31, 2019 at 21:15

2 Answers 2

3

Hey I suggest creating 2 classes for Deserialization

    public class UserInfo
    {
        [JsonProperty("user_info")]
        public Dictionary<string, Account> Users { get; set; }
    }

    public class Account
    {
        [JsonProperty("roles")]
        public List<string> Roles { get; set; }
    }

The deserialization could then look like this

        var info = JsonConvert.DeserializeObject<UserInfo>(jsonString);
        var allRoles = info.Users.SelectMany(x => x.Value.Roles);

The examle uses the Newtonsoft package

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

2

Similar to what @OwnBlood suggested, you can make two classes using the Newtonsoft.Json framework:

public class Application
{
    [JsonProperty("roles")]
    public IEnumerable<string> Roles { get; set; }
}

public class User
{
    [JsonProperty("user_info")]
    public IDictionary<string, Application> UserInfo { get; set; }
}

Then you can deserialize with the JsonConvert.DeserializeObject() method:

var deserializedJson = JsonConvert.DeserializeObject<User>(jsonString);

And you can create a method that filters out the roles from a specific application name using LINQ:

private static IEnumerable<string> GetUserApplicationRoles(string applicationName, User data) => 
    data.UserInfo
        .TryGetValue(applicationName, out var value) ?
            value.Roles : 
            Enumerable.Empty<string>();

Explanation:

  • Since UserInfo is a IDictionary<string, Application>, we can use TryGetValue to access the specific applicationName. This allows O(1) access.
  • Then we can simply return the IEnumerable<string> roles, or an empty collection, in this case Enumerable.Empty<string>.

Working demo found at dotnetfiddle.net

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.