Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Merge Firefox json bookmarks

0.00/5 (No votes)
5 Nov 2012 1  
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.
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here