Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#

Merge Firefox json bookmarks

Rate me:
Please Sign up or sign in to vote.
4.75/5 (3 votes)
5 Nov 2012CPOL 30.2K   437   8   4
A utility to merge 2 firefox json bookmark files while preserving tags, and directory struction

Introduction 

If you want to merge bookmarks from 2 machines (ex, work and home) firefox doesn't allow you to merge the bookmarks, it only allow you to replace the current bookmarks.

Background  

this code use jayrock json library to manipulate json text 

http://jayrock.berlios.de

Using the code

firefox bookmark file, are composed mainly of 4 arrays, Tags, Bookmark Menu, Bookmark Toolbar and unsorted bookmark.
C++
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jayrock.Json.Conversion;
using System.Collections;
using System.Windows.Forms;

namespace mergeBookmarks
{
    static class Merge
    {
        static int maxId = 0;
        static IDictionary findItem(string menu, string sUri,  Jayrock.Json.JsonArray jArray)
        {
            IDictionary foundNode = null;
            int i;
            for (i = 0; i < jArray.Count(); i++)
            {

                if (jArray[i].GetType() == typeof(Jayrock.Json.JsonObject))
                {
                    IDictionary node =(IDictionary) jArray[i];
                    if (node.Contains("title"))
                    {
                        if ((node["title"] == null && menu == null) || Convert.ToString(node["title"]).Equals(menu))
                        {
                            foundNode = (IDictionary)jArray[i];
                            if (node.Contains("uri"))
                            {
                                if (Convert.ToString(node["uri"]).Equals(sUri))
                                {
                                    return foundNode;
                                }
                            }
                            else
                            {
                                return foundNode;
                            }
                        }
                    }
                }
                else if (jArray[i].GetType() == typeof(Jayrock.Json.JsonArray))
                {
                }
                else
                {
                }
            }
            return foundNode;

        }
        static int findMaxIndex(Jayrock.Json.JsonArray jArray)
        {
            int index = 0;
            int i;
            for (i = 0; i < jArray.Count(); i++)
            {
                if (jArray[i].GetType() == typeof(Jayrock.Json.JsonObject))
                {
                     IDictionary node =(IDictionary)jArray[i];
                    if (node.Contains("index"))
                    {
                        if (Convert.ToInt32(node["index"])>index)
                            index = Convert.ToInt32(node["index"]);
                    }
                }
                else
                {
                }
            }
            return index;
        }
        static void adjustIds( int parent, Jayrock.Json.JsonArray jArray)
        {
            IEnumerator<object> jTagEnum = jArray.GetEnumerator();
            int index = 0;
            while (jTagEnum.MoveNext())
            {
                IDictionary obj= (IDictionary)jTagEnum.Current;
                obj["id"] = maxId++;
                obj["parent"] = parent;
                if (!obj.Contains("index"))
                {
                    if (index > 0)
                        obj.Add("index", index);
                }
                else
                {
                    obj["index"] = index;
                }
                index++;
                if (obj["type"].ToString().Equals("text/x-moz-place-container"))
                {
                    adjustIds(Convert.ToInt32(obj["id"]), (Jayrock.Json.JsonArray)obj["children"]);
                }
            }
        }

        static void doMergeLists(IDictionary node1, IDictionary node2)
        {
            string sType1, sType2;
            sType1 = node1["type"].ToString();
            sType2 = node2["type"].ToString();
            if (!sType1.Equals("text/x-moz-place-container") || !sType2.Equals("text/x-moz-place-container"))
            {
                throw new Exception("not container");
            }

            Jayrock.Json.JsonArray jArray1 = (Jayrock.Json.JsonArray)node1["children"];
            int TagsId = Convert.ToInt32(node1["id"]);
            Jayrock.Json.JsonArray jArray2 = (Jayrock.Json.JsonArray)node2["children"];
            int maxTagsIndex = findMaxIndex(jArray1) + 1;
            IEnumerator<object> jArray2Enum = jArray2.GetEnumerator();
            while (jArray2Enum.MoveNext())
            {
                IDictionary node = (IDictionary)jArray2Enum.Current;
                if (node.Contains("title"))
                {
                    string title=null;
                    if (node["title"] != null)
                        title = node["title"].ToString();
                    else
                        title = null;
                    string sItemType2 = node["type"].ToString();
                    if ((title != null && (title.Equals("Recently Bookmarked") || title.Equals("Recent Tags"))) || sItemType2 == "text/x-moz-place-separator")
                    {
                        continue;
                    }
                    IDictionary obj = null;
                    if (node.Contains("uri"))
                    {
                        string sUri = node["uri"].ToString();
                         obj = findItem(title, sUri, jArray1);
                    }
                    else
                    {
                         obj = findItem(title, "", jArray1);
                    }
                    if (obj != null)
                    {
                        string sItemType1 = obj["type"].ToString();
                        if (sItemType1.Equals(sItemType2))
                        {
                            // equal Types, then will do merge
                            if(sItemType1.Equals("text/x-moz-place"))
                            {
                                string sUri = node["uri"].ToString();
                                if (node["uri"].ToString().Equals(obj["uri"].ToString()))
                                {
                                    // equal title and uri, do nothing
                                }
                                else
                                {
                                    // equal title, but different uri, rename node
                                    int i = 1;
                                    IDictionary tObj;
                                    if (title != null)
                                    {
                                        while ((tObj = findItem(title + "(" + i + ")", sUri, jArray1)) != null)
                                        {
                                            i++;
                                        }
                                    }
                                    string obj1Text = node.ToString();
                                    if (!node.Contains("index"))
                                    {
                                        obj1Text = obj1Text.Insert(1, "\"index\":" + maxTagsIndex.ToString() + ",");
                                    }
                                    IDictionary obj1 = (IDictionary)JsonConvert.Import(obj1Text);
                                    int objId = maxId++;
                                    if(title != null)
                                        obj1["title"] = obj1["title"].ToString() + "(" + i + ")";

                                    obj1["id"] = objId;
                                    obj1["parent"] = TagsId;
                                    obj1["index"] = maxTagsIndex++;
                                    if (obj1["type"].ToString().Equals("text/x-moz-place-container"))
                                        adjustIds(objId, (Jayrock.Json.JsonArray)obj1["children"]);
                                    jArray1.Add(obj1);
                                }
                            }
                            else
                            {
                                // merge lists
                                doMergeLists(obj, node);
                            }
                        }
                        else
                        {
                            // types not equal, rename node
                            int i = 1;
                            IDictionary tObj;
                            string sUri1 = null;
                            if(node.Contains("uri"))
                                 sUri1 = node["uri"].ToString();
                            while ((tObj = findItem(title + "(" + i + ")",sUri1, jArray1)) != null)
                            {
                                i++;
                            }
                            string obj1Text = node.ToString();
                            if (!node.Contains("index"))
                            {
                                obj1Text = obj1Text.Insert(1, "\"index\":" + maxTagsIndex.ToString() + ",");
                            }
                            IDictionary obj1 = (IDictionary)JsonConvert.Import(obj1Text);
                            int objId = maxId++;
                            obj1["title"] = obj1["title"].ToString() + "(" + i + ")";
                            obj1["id"] = objId;
                            obj1["parent"] = TagsId;
                            obj1["index"] = maxTagsIndex++;
                            adjustIds(Convert.ToInt32(obj1["id"]), (Jayrock.Json.JsonArray)obj1["children"]);
                            jArray1.Add(obj1);

                        }
                    }
                    else
                    {
                        // not duplicate node
                            string obj1Text = node.ToString();
                            if (!node.Contains("index"))
                            {
                                obj1Text = obj1Text.Insert(1, "\"index\":" + maxTagsIndex.ToString() + ",");
                            }
                            IDictionary obj1 = (IDictionary)JsonConvert.Import(obj1Text);
                            int objId = maxId++;
                            obj1["id"] = objId;
                            obj1["parent"] = TagsId;
                            obj1["index"] = maxTagsIndex++;
                            if(sItemType2.Equals("text/x-moz-place-container"))
                                adjustIds(Convert.ToInt32(obj1["id"]), (Jayrock.Json.JsonArray)obj1["children"]);
                            jArray1.Add(obj1);
                    }
                }
            }
        }

        static int findMaxId( ref int id,Jayrock.Json.JsonArray jArray )
        {
            int i;
            for (i = 0; i < jArray.Count(); i++)
            {
                if (jArray[i].GetType() == typeof(Jayrock.Json.JsonObject))
                {
                    findMaxId(ref id, (IDictionary)jArray[i]);

                }
                else if (jArray[i].GetType() == typeof(Jayrock.Json.JsonArray))
                {
                    findMaxId(ref id, (Jayrock.Json.JsonArray)jArray[i]);
                }
                else
                {
//                    parseItem(jArray[i]);
                    Console.WriteLine(" {0,-25} {1}", ((DictionaryEntry)jArray[i]).Key, ((DictionaryEntry)jArray[i]).Value.GetType().ToString(), ((DictionaryEntry)jArray[i]).Value.ToString());
                }
            }
            return id;
        }
        static int findMaxId(ref int id, IDictionary node)
        {
            
            if(node.Contains("id")){
                if(Convert.ToInt32( node["id"]) > id)
                    id=Convert.ToInt32(node["id"]);
            }
            IDictionaryEnumerator dict = node.GetEnumerator();
            while (dict.MoveNext())
            {
                if (dict.Value == null)
                {
                }
                else if (dict.Value.GetType() == typeof(Jayrock.Json.JsonArray))
                {
                    findMaxId(ref id, (Jayrock.Json.JsonArray)dict.Value);
                }
                else if (dict.Value.GetType() == typeof(Jayrock.Json.JsonObject))
                {
                    findMaxId(ref id, (IDictionary)dict.Value);
                }
            } 

            return id;
        }
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmMerge());
        }
        public static void MergeBookmarks(string srcFile1, string srcFile2, string DstFile)
        {
            string jsontext = System.IO.File.ReadAllText(srcFile1);
            IDictionary root1 = (IDictionary)JsonConvert.Import(jsontext);
             jsontext = System.IO.File.ReadAllText(srcFile2);
            IDictionary root2 = (IDictionary)JsonConvert.Import(jsontext);
            int id = 0;
            findMaxId(ref id, root1);
            maxId = id+1;
            doMergeLists(root1, root2);
            System.IO.File.WriteAllText(DstFile, root1.ToString());
        }
    }
}

Points of Interest

jayrock json library is very nice and easy to use tool

History

 first release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to use thia code? Pin
Simon K B12-Feb-13 4:28
Simon K B12-Feb-13 4:28 
QuestionHow do I use this exactly? Pin
5moufl28-Aug-12 23:08
5moufl28-Aug-12 23:08 
GeneralMy vote of 4 Pin
Klaus Luedenscheidt17-Jun-12 17:18
Klaus Luedenscheidt17-Jun-12 17:18 
GeneralRe: My vote of 4 Pin
AmrEmam20-Jun-12 13:08
AmrEmam20-Jun-12 13:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.