Nikunj Chaklasiya
Nikunj Chaklasiya

Reputation: 818

How to put multiple values in Dictionary instances using LINQ?

My Json Response is Following below:

{"d":
{"RowData": 
[{"GenreId":11,"GenreName":"Musical","subjecturl":"subjecturl_1","logourl":"logourl_1"},
{"GenreId":12,"GenreName":"kids","subjecturl":"subjecturl_2","logourl":"logourl_2"},
{"GenreId":13,"GenreName":"other","subjecturl":"subjecturl_3","logourl":"logourl_3"},
{"GenreId":14,"GenreName":"Musical","subjecturl":"subjecturl_4","logourl":"logourl_4"},
{"GenreId":15,"GenreName":"Music","subjecturl":"subjecturl_5","logourl":"logourl_5"},
{"GenreId":16,"GenreName":"Faimaly","subjecturl":"subjecturl_6","logourl":"logourl_6"},
{"GenreId":17,"GenreName":"other","subjecturl":"subjecturl_7","logourl":"logourl_7"},
{"GenreId":18,"GenreName":"other","subjecturl":"subjecturl_8","logourl":"logourl_8"},
{"GenreId":19,"GenreName":"kids","subjecturl":"subjecturl_9","logourl":"logourl_9"},
{"GenreId":20,"GenreName":"Musical","subjecturl":"subjecturl_10","logourl":"logourl_10"},
{"GenreId":21,"GenreName":"other","subjecturl":"subjecturl_11","logourl":"logourl_11"}]}}

Using the above Response I tried to make like below Response :

{"rows": [{
        "title": "Musical",
        "items": [{"hdsubjecturl": "subjecturl_1"},{"hdsubjecturl": "subjecturl_4"},{"hdsubjecturl": "subjecturl_10"}]
        },{
        "title": "kids",
        "items": [{"hdsubjecturl": "subjecturl_2"},{"hdsubjecturl": "subjecturl_9"}]
        },{
        "title": "Music",
        "items": [{"hdsubjecturl": "subjecturl_5"}]
        },{
        "title": "other",
        "items": [{"hdsubjecturl": "subjecturl_3"},{"hdsubjecturl": "subjecturl_7"},{"hdsubjecturl": "subjecturl_8"},{"hdsubjecturl": "subjecturl_11"}]
        },{
        "title": "Faimaly",
        "items": [{"hdsubjecturl": "subjecturl_6"}]
        }]
}

My Code is below :

JObject Root = JObject.Parse(jsonData["d"].ToString());
var unique = Root["RowData"].GroupBy(x => x["GenreName"]).Select(x => x.First()).ToList(); // here fetch 5 record
foreach (var un in unique)
{
      var GenreName = new
      {
               title = un["GenreName"],
               items = new
               {
                     hdsubjecturl = "logourl"
               }
      };
      var GenreNamereq = JsonConvert.SerializeObject(GenreName, Newtonsoft.Json.Formatting.Indented);
      genstr.Append(GenreNamereq, 0, GenreNamereq.Length);
      genstr.Append(",");
      using (System.IO.StreamWriter file = new System.IO.StreamWriter(subdir + "\\GenreName.json"))
      {
              string st = genstr.ToString().Substring(0, (genstr.Length - 1));
              file.WriteLine("{\n\"rows\": [\n" + st + "\n}"); //seasion number 21 terminate
              file.Close();
      }
}

Using above code my output is below for First Field :

{"rows":
    [{
       "title": "Musical",
         "items": {
            "hdsubjecturl": "logourl"
          }
    }]
}

Using below code I tried to fetch Multiple values using specific Field :

List<string> CategoryList = new List<string>();
var unique = Root["RowData"].GroupBy(x => x["GenreName"]).Select(x => x.First()).ToList(); // here fetch 8 record
foreach (var cat in unique)
{
     CategoryList.Add(cat["GenreName"].ToString());
}

List<List<string>> myList = new List<List<string>>();

for (int i=0;i<CategoryList.Count();i++)
{
     var results = from x in Root["RowData"]
                   where x["GenreName"].Value<string>() == CategoryList[i]
                   select x;

                   foreach (var token in results)
                   {
                      Console.WriteLine(token["logourl"]);
                   }
                   // myList.Add(results);
}

In the First code, I used JObject for fetching a Root node. But, using the above query it takes by default JTocken. So, I used foreach loop here. I used Dictionary instances for JSON Creation. Using this code I successfully fetched hdsubjecturl in for loop. But, I don't know how to put multiple values in Dictionary instances. Because I get title fields only single times using a unique query and items fields inside a hdsubjetcurl is more than one. Does anyone know how it's possible?

Upvotes: 1

Views: 813

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23258

You can group your RowData by GenreName token, then use ToDictionary method to get a result dictionary and map it to desired structure (with title and hdsubjecturl). Finally create a result object using JObject.FromObject

var json = JObject.Parse(jsonString);

var data = json["d"]?["RowData"]
    .GroupBy(x => x["GenreName"], x => x["subjecturl"])
    .ToDictionary(g => g.Key, g => g.ToList())
    .Select(kvp => new { title = kvp.Key, items = kvp.Value.Select(x => new { hdsubjecturl = x }) });

var result = JObject.FromObject(new { rows = data });
Console.WriteLine(result);

It gives you the expected result.

Edit: according to comments, GroupBy and Select expressions should be updated to map more then one property in result title item

var data = json["d"]?["RowData"]
    .GroupBy(x => x["GenreName"])
    .ToDictionary(g => g.Key, g => g.ToList())
    .Select(kvp => new
    {
        title = kvp.Key,
        items = kvp.Value.Select(x => new { hdsubjecturl = x["subjecturl"], url = x["logourl"] })
    });

var result = JObject.FromObject(new { rows = data });

Upvotes: 1

Jakub Kozera
Jakub Kozera

Reputation: 3493

Consider trying this code, (using Newtonsoft Json deserializer);

    public partial class Root
    {
        public D D { get; set; }
    }

    public partial class D
    {
        public RowDatum[] RowData { get; set; }
    }

    public partial class RowDatum
    {
        public long GenreId { get; set; }
        public string GenreName { get; set; }
        public string Subjecturl { get; set; }
        public string Logourl { get; set; }
    }

    public partial class Response
    {
        public Row[] Rows { get; set; }
    }

    public partial class Row
    {
        public string Title { get; set; }
        public Item[] Items { get; set; }
    }

    public partial class Item
    {
        public string Hdsubjecturl { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {

            var json =
                @"{""d"":{""RowData"":[{""GenreId"":11,""GenreName"":""Musical"",""subjecturl"":""subjecturl_1"",""logourl"":""logourl_1""},{""GenreId"":12,""GenreName"":""kids"",""subjecturl"":""subjecturl_2"",""logourl"":""logourl_2""},{""GenreId"":13,""GenreName"":""other"",""subjecturl"":""subjecturl_3"",""logourl"":""logourl_3""},{""GenreId"":14,""GenreName"":""Musical"",""subjecturl"":""subjecturl_4"",""logourl"":""logourl_4""},{""GenreId"":15,""GenreName"":""Music"",""subjecturl"":""subjecturl_5"",""logourl"":""logourl_5""},{""GenreId"":16,""GenreName"":""Faimaly"",""subjecturl"":""subjecturl_6"",""logourl"":""logourl_6""},{""GenreId"":17,""GenreName"":""other"",""subjecturl"":""subjecturl_7"",""logourl"":""logourl_7""},{""GenreId"":18,""GenreName"":""other"",""subjecturl"":""subjecturl_8"",""logourl"":""logourl_8""},{""GenreId"":19,""GenreName"":""kids"",""subjecturl"":""subjecturl_9"",""logourl"":""logourl_9""},{""GenreId"":20,""GenreName"":""Musical"",""subjecturl"":""subjecturl_10"",""logourl"":""logourl_10""},{""GenreId"":21,""GenreName"":""other"",""subjecturl"":""subjecturl_11"",""logourl"":""logourl_11""}]}}";

            var root = JsonConvert.DeserializeObject<Root>(json);

            var rows = root.D.RowData.ToLookup(d => d.GenreName)
                .Select(g => new Row()
                {
                    Title = g.Key,
                    Items = g.ToList().Select(rd => new Item() {Hdsubjecturl = rd.Logourl}).ToArray()
                }).ToArray();

            var response = new Response()
            {
                Rows = rows
            }; // reponse is the type of Json Response you wanted to achieve

            Console.WriteLine();

        }


    }

Upvotes: 1

Related Questions