-1

I want to convert JSON to object. The code below works fine.

internal class Program
{
    static void Main(string[] args)
    {
        string json = @"{
                  'name': 'Ayrton Senna',
                  'friends': [
                    {
                      'name': 'John',
                      'age': 34
                    },
                    {
                      'name': 'Jack',
                      'age': 32
                    }
                  ]
                }";

        var person = JsonConvert.DeserializeObject<Person>(json);
    }

    public class Person
    {
        public string Name { get; set; }
        public List<Friend> Friends { get; set; }

        public class Friend
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }
}

However in the Person Class I want the property List to be dictionary. The key will be string that should be "friends" (somehow taken from the Json and not hardcoded). The value will be list of objects.

Example:

    public class Person
    {
        public string Name { get; set; }
        public Dictionary<string, List<Friend>> Friends { get; set; }

        public class Friend
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }

The reason I want this is so when i will have different JSON for example:

{
  "id": 1,
  "name": "Ayrton Senna",
  "mates": [
    {
      "name": "John",
      "age": 12
    },
    {
      "name": "Jack",
      "age": 32
    }
  ]
}

Another example Json:

{
  "id": 1,
  "name": "Ayrton Senna",
  "companions": [
    {
      "name": "John",
      "age": 12
    },
    {
      "name": "Jack",
      "age": 32
    }
  ]
}

I need to capture/store the name of the list like: "friends", "mates", "companions" because i will need to display them later. I will have 20 Json files like this and only this property name will be different. So i need to read ir from the json and store it somehow.

I want a class that will be more "generic".

Is this even doable? If you have some other suggestions please do tell. Any help will be much appreciated!

Happy Coconut
  • 973
  • 4
  • 14
  • 33
  • The only difference between json I see that friends are replaced by mates. Do you hiding something? And what is going to be a key of your Dictionary? name or Id? – Serge Feb 13 '23 at 20:30
  • maybe I am bad at explaining. The key of the dictionary on the first json i want to be "friends" and on the second "mates". The name of the dictionary property is irrelevant. I will have around 20 different jsons with the same structure but the name of the "friends" property/array will be allways different. I need to read it and show it on a display. That is why I need to store it somewhere. – Happy Coconut Feb 13 '23 at 20:36
  • 1
    Can you post at least one more json to see the difference. I don't understand what do you want. YOu have only one person. Why do you need a dictionary, not just a class instance? – Serge Feb 13 '23 at 20:44
  • I updated the question. I hope it is more clear now. – Happy Coconut Feb 13 '23 at 20:51
  • 1
    Does [this answer](https://stackoverflow.com/a/40094403/3744182) to [How to deserialize a child object with dynamic (numeric) key names?](https://stackoverflow.com/q/40088941/3744182) answer your question? Apply `[JsonConverter(typeof(TypedExtensionDataConverter))]` to `Person` and `[JsonTypedExtensionData]` to `public Dictionary> Friends { get; set; }` and you should be good to go. – dbc Feb 13 '23 at 21:05
  • 1
    I think you're approaching this incorrectly. I think you should map to another poco that is your new schema, map between the two with something like automapper. You're trying to "map" using a serialiser, use a mapper, is my advice. – Dan Rayson Feb 13 '23 at 22:52

2 Answers2

1

if the only difference is the array name, you can leave the class you have already and use this code

    var jObj = JObject.Parse(json);
    var friends =  jObj.Properties()
                      .Where(p => p.Value.Type == JTokenType.Array)
                      .SingleOrDefault();
                    
    Person person = jObj.ToObject<Person>();
    person.FriendsKind= friends.Name;
    person.Friends = friends.Value.Select(p => p.ToObject<Friend>()).ToList();

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string FriendsKind {get; set;}
    public List<Friend> Friends { get; set; }
}
Serge
  • 40,935
  • 4
  • 18
  • 45
  • Tried this code. It only works if it is for friends. What if I use Mates instead of Friends. The object will have the Friends property list. – Happy Coconut Feb 13 '23 at 22:19
  • @HappyCoconut You didn't tell that you need an array name too. I can't see what do you need it for but I will add it to you – Serge Feb 13 '23 at 22:23
  • in the edited question and in the comments I said "I need to read it and show it on a display." Sorry for misunderstanding – Happy Coconut Feb 13 '23 at 22:25
1
    var jObj = JObject.Parse(json);
    var friends = jObj.Properties().ToArray()[1];
    
    var person = new Person
    {
        Name = jObj.GetValue("name").Value<string>(),
        Friends = new Dictionary<string, List<Person.Friend>>
        {
            {
                friends.Name,
                friends.Value.Select(p => p.ToObject<Person.Friend>()).ToList()
            }
        }
    };

    public class Person
    {
        public string Name { get; set; }
        public Dictionary<string, List<Friend>> Friends { get; set; }

        public class Friend
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }
Arvis
  • 8,273
  • 5
  • 33
  • 46