2

In my application I want to show a folder and its containing bookmarks. I try to achieve something like this:

  • folder Wikipedia
    • url a
    • url b
    • url ...
  • folder StackOverflow
    • url a
    • url b

Therefore I have to parse the following json string:

{
       "checksum": "7d7205349eb64a4894aafc5ce074c0c0",
       "roots": {
          "bookmark_bar": {
             "children": [ {
                "children": [ {
                   "date_added": "13021579661026871",
                   "id": "28",
                   "name": "design patterns - Do you allow the Web Tier to access the DAL directly? - Stack Overflow",
                   "type": "url",
                   "url": "http://stackoverflow.com/questions/796656/do-you-allow-the-web-tier-to-access-the-dal-directly"
                }, {
                   "date_added": "13021665700468056",
                   "id": "31",
                   "name": "VS 2010 Error when creating or opening projects - Stack Overflow",
                   "type": "url",
                   "url": "http://stackoverflow.com/questions/8403853/vs-2010-error-when-creating-or-opening-projects"
                } ],
                "date_added": "13021579680308871",
                "date_modified": "13024947520078515",
                "id": "29",
                "name": "StackOverflow",
                "type": "folder"
             }, {
                "children": [ {
                   "date_added": "13022096980978880",
                   "id": "45",
                   "name": "Dependency injection - Wikipedia, the free encyclopedia",
                   "type": "url",
                   "url": "http://en.wikipedia.org/wiki/Dependency_injection"
                }, {
                   "date_added": "13024941326636844",
                   "id": "124",
                   "name": "Strategy pattern - Wikipedia, the free encyclopedia",
                   "type": "url",
                   "url": "http://en.wikipedia.org/wiki/Strategy_pattern"
                } ],
                "date_added": "13023315356559470",
                "date_modified": "13024946156966435",
                "id": "72",
                "name": "Wiki",
                "type": "folder"
             }, {
                "children": [ {
                   "date_added": "13023667785042757",
                   "id": "85",
                   "name": "Anemic Domain Model Illustrated | Frequent incoherent cogitation",
                   "type": "url",
                   "url": "http://vitamic.wordpress.com/2007/01/04/anemic-domain-model-illustrated/"
                } ],
                "date_added": "13023667668403520",
                "date_modified": "13023668043391377",
                "id": "82",
                "name": "#Read",
                "type": "folder"
             }, {
                "date_added": "13025102943539897",
                "id": "130",
                "name": "Modern UI for WPF - Home",
                "type": "url",
                "url": "http://mui.codeplex.com/wikipage?title=screenshots&referringTitle=Home"
             } ],
             "date_added": "13020681767991841",
             "date_modified": "13025102947408897",
             "id": "1",
             "name": "Lesezeichenleiste",
             "type": "folder"
          }
       },
       "version": 1
    }

I have tried the GroupBy Function, like this without success:

    var items = jObject.Descendants()
                     .Where(x => x.Type == JTokenType.Object &&
                                 x.Value<string>("type") != null)
                     .GroupBy(x => x.Value<string>("type"));

    foreach (var item in items)
    {
        Console.WriteLine(item.Key.ToString());
        foreach (var children in item)
        {
            Console.WriteLine("    " + children.Value<string>("name"));
        }
    }

I have also tried do apply the Join Function but I am missing a join property here. Can someone point me in the right direction please?

1 Answer 1

6

I would parse that json using concrete classes.

var root = JsonConvert.DeserializeObject<RootObj>(json);
Print(root.roots.bookmark_bar,"");

 

void Print(Node n,string padding)
{
    Console.WriteLine(padding + "+" + n.name);
    foreach(var url in n.children.Where(c => c.type == "url"))
    {
        Console.WriteLine(padding + "\t-" + url.name);
    }
    foreach (var folder in n.children.Where(c => c.type == "folder"))
    {
        Print(folder, padding + "\t");
    }
}

 

public class Node
{
    public string date_added { get; set; }
    public string date_modified { get; set; }
    public string id { get; set; }
    public string name { get; set; }
    public string type { get; set; }
    public string url { get; set; }
    public List<Node> children { get; set; }
}

public class Roots
{
    public Node bookmark_bar { get; set; }
}

public class RootObj
{
    public string checksum { get; set; }
    public Roots roots { get; set; }
    public int version { get; set; }
}

Above code is enough to parse your json, but if you want *date_modified* and *date_added* fields as DateTime, you can implement a JsonConverter class

var root = JsonConvert.DeserializeObject<RootObj>(json, new DateTimeConverter());

 

class DateTimeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return new DateTime(1970,1,1).Add(TimeSpan.FromTicks(long.Parse((string)reader.Value)));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then your Node class will be

public class Node
{
    public DateTime date_added { get; set; }
    public DateTime date_modified { get; set; }
    public string id { get; set; }
    public string name { get; set; }
    public string type { get; set; }
    public string url { get; set; }
    public List<Node> children { get; set; }
}
Sign up to request clarification or add additional context in comments.

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.