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))
{
if(sItemType1.Equals("text/x-moz-place"))
{
string sUri = node["uri"].ToString();
if (node["uri"].ToString().Equals(obj["uri"].ToString()))
{
}
else
{
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
{
doMergeLists(obj, node);
}
}
else
{
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
{
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
{
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