-1

I am trying to deserialize different items in a json object. Struggling how to create an object based on the following response.

{
   "a374e91a9f513c79a8961de7c494cf799bbdb35b":{
      "rd":[
         {
            "1":{
               "filename":"The Lion King (2019) BluRay 1080p x264 (nItRo)-XpoZ.mkv",
               "filesize":1819821931
            }
         }
      ]
   },
   "e999ddbb3e18613476546684e34a4a6b0cfec878":{
      "rd":[
         {
            "1":{
               "filename":"The.Lion.King.2019.1080p.BluRay.10bit.x265-HazMatt.mkv",
               "filesize":4256678521
            }
         }
      ]
   },
   "8bb877768a0780c9694767a655720927e6cda57e":{
      "rd":[
         
      ]
   },
   "054139ba17b8fdd8df1538e1857c45240d5c9368":[
      
   ]
}

I would like to map it to the following C# structure

var items = JsonConvert.DeserializeObject<List<Item>>(jsonResponse);

Public class Item
{
   public string Key {get; set;} // Example a374e91a9f513c79a8961de7c494cf799bbdb35b
   
   public List<Files> Files {get; set;}

}

Public class File
{
    public string Id{get; set;} // "1"
    public string FileName {get; set;} // The Lion King (2019) BluRay 1080p x264 (nItRo)-XpoZ.mkv
    public long FileSize {get; set:} // 1819821931
}

Update

Note that the "rd" property name isn't a fixed string, it can also have different values.

Magik
  • 35
  • 4
  • 2
    Your JSON doesn't represent an array - it represents an object with various properties. You should probably deserialize it as a `Dictionary` - although your class doesn't mention `rd` anywhere... I suspect your `Files` property should actually be a `Dictionary` with `[JsonProperty("rd")]` on it... – Jon Skeet Jan 26 '23 at 20:36

2 Answers2

1

When you have a JSON object with runtime-only JSON property names such as "a374e91a9f513c79a8961de7c494cf799bbdb35b" and "1", you should deserialize to a dictionary.[1]

Specifically, define a class for the inner object that has a static Rd property like so:

public record Item ([property: JsonProperty("rd")] List<Dictionary<string, File>> Rd);

(Here I am using a record for brevity, but you could just as easily use the more traditional class style.)

And now you can do:

var root = JsonConvert.DeserializeObject<Dictionary<string, Item>>(json);

You should also remove Id from File since the file ID will be the dictionary key:

public class File
{
    public string FileName {get; set;} // The Lion King (2019) BluRay 1080p x264 (nItRo)-XpoZ.mkv
    public long FileSize {get; set;} // 1819821931
}

Demo fiddle here.

Update

"rd" itself isn't a fixed string, it can also have different values.

In that case, eliminate Item and deserialize to Dictionary<string, Dictionary<string, List<Dictionary<string, File>>>>:

var root = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, List<Dictionary<string, File>>>>>(json);

Demo fiddle #2 here.


[1] See this answer by Jon Skeet to Deserializing JSON with unknown object names.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Thank you very much for the response.... one question, I forgot to clarify that "rd" itself isn't a fixed string, it can also have different values... so I can't create JsonProperty("rd")... what should I do then? I guess I will have to go with something like this -> Dictionary>> ? – Magik Jan 27 '23 at 01:09
  • Hello, so while testing the responses coming from the Rest API, I found another usecase... the last element in the JSON cant even be mapped to Dictionary. Would you be able to help how the edited json can be Deserialize? Thanks – Magik Feb 05 '23 at 06:01
  • @Magik - the recommended format for questions is [one per post](https://meta.stackexchange.com/q/222735), so I'd suggest asking a new question rather as opposed to editing your old question and adding requirements that invalidate the current answers. – dbc Feb 05 '23 at 06:11
  • @Magik - but maybe see [Deserialize JSON when a value can be an object or an empty array](https://stackoverflow.com/q/29449641/3744182). – dbc Feb 05 '23 at 06:15
0

if you want to map json data to your class you will have to parse json at first, after this to convert it to a class you need

List<Item> items = JObject.Parse(json).Properties()
.Select(jo => new Item
{
    Key = jo.Name,
    Files = jo.Value["rd"].Select(ja => ((JObject)ja)).Properties()
    .Select(p => new File
    {
        Id = p.Name,
        FileName = (string)p.Value["filename"],
        FileSize = (long)p.Value["filesize"]
    }).ToList()
}).ToList();

UPDATE

This is a version without using "rd" property name

List<Item> items = JObject.Parse(json).Properties()
   .Select(jo => new Item
   {
       Key = jo.Name,
       Files = new JObject(((JObject)jo.Value)
   .Properties().First()).Properties().First().Value
   .SelectMany(v => ((JObject)v).Properties()
   .Select(i => new File
   {
       Id = i.Name,
       FileName = (string)i.Value["filename"],
       FileSize = (long)i.Value["filesize"]
   })).ToList()
   }).ToList();

output

[
  {
    "Key": "a374e91a9f513c79a8961de7c494cf799bbdb35b",
    "Files": [
      {
        "Id": "1",
        "FileName": "The Lion King (2019) BluRay 1080p x264 (nItRo)-XpoZ.mkv",
        "FileSize": 1819821931
      }
    ]
  },
  {
    "Key": "e999ddbb3e18613476546684e34a4a6b0cfec878",
    "Files": [
      {
        "Id": "1",
        "FileName": "The.Lion.King.2019.1080p.BluRay.10bit.x265-HazMatt.mkv",
        "FileSize": 4256678521
      }
    ]
  },
  {
    "Key": "8bb877768a0780c9694767a655720927e6cda57e",
    "Files": []
  }
]
Serge
  • 40,935
  • 4
  • 18
  • 45