Ragnarok
Ragnarok

Reputation: 3

Accessing list of object inside an object

I have class named ResponseModel and one object inside that class named Errors refer to the class ErrorsResponseModel, and that class has bunch of objects which have List<string> data type . I would like to know on how to accessing the List<string> objects without going through like: VariableClassA.ObjectOfClassAWhichReferToTheClassB.FirstListOfString and VariableClassA.ObjectOfClassAWhichReferToTheClassB.SecondListOfString, the data of List<string> objects comes from the JSON data.

I have tried only to access one object per one object as I am not really sure on how to do generic without going through one object per one object, which is if I update the model of class B itself, then I need to make sure that I didn't missed out the necessary checking of that newly created object inside class B.

Here is the code of the model:

public sealed class ResponseModel
{
    public ErrorsResponseModel Errors { get; set; }
}

public sealed class ErrorsResponseModel
{
    public List<string> Username { get; set; }
    public List<string> Password { get; set; }
    public List<string> Nickname { get; set; }
}

Here is what I have tried so far:

string jsonData = "{"Errors":{"Username":["The username field is required."],"Password":["The password field is required."],"Nickname":["The nickname field is required."]}}";

var jsonConvertedData = JsonConvert.DeserializeObject<ResponseModel>(jsonData);

var usernameErrors = jsonConvertedData.Errors.Username;

var passwordErrors = jsonConvertedData.Errors.Password;

var nicknameErrors = jsonConvertedData.Errors.Nickname;

I expect to loop any object of class ErrorsResponseModel that the length of List<string> inside that class is more than 0 . I can't change the response data from the JSON, as it is comes from the third party.

EDIT: I have tried the following in JavaScript and it works, how can I do the same in C#?

in C#, I return to the front end like using the following return Json(jsonConvertedData), and in frontend, I do like the following:

$.ajax({
..... the AJAX settings

success: function (data) {
$.each(data.Errors, function (i, v) {
  if (v.length > 0) {
       console.log(v);
    }
});
}

The above code in Javascript is looping through the message inside each object inside ErrorsResponseModel and read it through to the console.

Upvotes: 0

Views: 1020

Answers (2)

shingo
shingo

Reputation: 27154

Let ErrorsResponseModel inherit Dictionary

public sealed class ErrorsResponseModel : Dictionary<string, List<string>>
{
    //If you still want to access data with property.
    public List<string> Username => this["Username"];
    ...
}

Now you can loop through Errors like a normal dictionary

foreach (var item in jsonConvertedData.Errors)
    if(item.Value.Count > 0)
       Console.WriteLine($"{item.Key} => {item.Value[0]}");

dynamic is another choice

var jsonConvertedData = JsonConvert.DeserializeObject<dynamic>(jsonData);

foreach (var item in jsonConvertedData.Errors)
    if(item.Count > 0)
        foreach(var v in item.Value)
            Console.WriteLine(v);

Upvotes: 1

Rufus L
Rufus L

Reputation: 37050

One way to do this would be to create a class to hold the related data, for example:

class User
{
    public string Name { get; set; }
    public string Nickname { get; set; }
    public string Password { get; set; }
}

Then we can make a method that populates a list of this class from the ErrorsResponseModel class (after first validating that the counts of all the lists are the same):

public List<User> GetUsers(ErrorsResponseModel errors)
{
    if (errors == null || errors.Username == null) return null;
    if (errors.Username.Count == 0) return new List<User>();

    if (errors.Nickname?.Count != errors.Password?.Count ||
        errors.Password?.Count != errors.Username.Count)
    {
        throw new InvalidDataException("Unequal number of Usernames/Passwords/Nicknames");
    }

    return errors.Username
        .Select((userName, index) =>
        new User
        {
            Name = userName,
            Nickname = errors.Nickname[index],
            Password = errors.Password[index]
        }).ToList();
}

Upvotes: 0

Related Questions