Search code examples
javajsonbookmarks

How to extract each element (Bookmark) from a json file as an item using Java?


I’m trying to extract my bookmarks from Chrome’s bookmarks file, which is stored in the json format. I have a large number of bookmarks. This sample file below is a new Google profile to make a small number of elements for a workable file.

So far I have constructed a java program to iterate through the file and extract the keys. My problem is that some of the keys are arrays and have multiple keys in the item. At present I’m trying to figure out how to get those individual elements.

Each of the bookmarks are identified with a unique ID. So if I can get the key by ID, then associate each of the other elements of the key with that unique ID, I believe I’ll have each of the bookmarks.

My final objective is to put the bookmarks into a database so that I can have a better way of organizing them such as, searching, finding duplicates, categorizing and adding comments, etc.

My java program is the below. Also below the java program is the output after running it on the attached Chrome bookmark file.

Bookmarks file:
Bookmarks.json:

{
   "checksum": "d27be6b28b9a8879c2cb9ba6fc90df21",
   "roots": {
      "bookmark_bar": {
         "children": [ {
            "date_added": "13081990058553125",
            "id": "7",
            "meta_info": {
               "stars.id": "ssc_c257c6390425956c",
               "stars.version": "sync.server.Chrome45"
            },
            "name": "Google",
            "sync_transaction_version": "1",
            "type": "url",
            "url": "https://www.google.com/"
         }, {
            "date_added": "13078166246742000",
            "id": "9",
            "meta_info": {
               "stars.flags": "5",
               "stars.id": "ssc_7150b291c6b52a37",
               "stars.pageData": "Ig5keGVLcUJvcW5kTjZSTQ==",
               "stars.type": "2"
            },
            "name": "Apollo III Communications",
            "sync_transaction_version": "1",
            "type": "url",
            "url": "http://www.apollo3.com/"
         } ],
         "date_added": "13113606994595146",
         "date_modified": "13083379523340359",
         "id": "1",
         "name": "Bookmarks bar",
         "type": "folder"
      },
      "other": {
         "children": [  ],
         "date_added": "13113606994595154",
         "date_modified": "0",
         "id": "2",
         "name": "Other bookmarks",
         "type": "folder"
      },
      "sync_transaction_version": "5",
      "synced": {
         "children": [  ],
         "date_added": "13113606994595157",
         "date_modified": "0",
         "id": "3",
         "name": "Mobile bookmarks",
         "type": "folder"
      }
   },
   "version": 1
}

Java Program to iterate through and extract the bookmarks:
getChromeBookmarks.java

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public class getChromeBookmarks {

    @SuppressWarnings("resource")
    public static void main(String[] args) {

        String infile = "/home/users/l/j/ljames/work/json/Bookmarks.json";

        String content = null;
        try {
            content = new Scanner(new File(infile)).useDelimiter("\\Z").next();         
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        JSONParser parser = new JSONParser();
        try {
            JSONObject json = (JSONObject) parser.parse(content);
            printJsonObject(json);

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static void printJsonObject(JSONObject jsonObj) {
        for (Object key : jsonObj.keySet()) {
            // based on the key types
            String keyStr = (String) key;
            Object keyvalue = jsonObj.get(keyStr);

            // Print key and value
            System.out.println("key: " + keyStr + " value: " + keyvalue);

            // expand(keyvalue);

            // for nested objects iteration if required
            if (keyvalue instanceof JSONObject)
                printJsonObject((JSONObject) keyvalue);
        }
    }
}

Output of the java/jason program:

key: checksum value: d27be6b28b9a8879c2cb9ba6fc90df21
key: roots value: {"other":{"date_added":"13113606994595154","date_modified":"0","children":[],"name":"Other bookmarks","id":"2","type":"folder"},"synced":{"date_added":"13113606994595157","date_modified":"0","children":[],"name":"Mobile bookmarks","id":"3","type":"folder"},"bookmark_bar":{"date_added":"13113606994595146","date_modified":"13083379523340359","children":[{"date_added":"13081990058553125","meta_info":{"stars.id":"ssc_c257c6390425956c","stars.version":"sync.server.Chrome45"},"name":"Google","id":"7","type":"url","url":"https:\/\/www.google.com\/","sync_transaction_version":"1"},{"date_added":"13078166246742000","meta_info":{"stars.pageData":"Ig5keGVLcUJvcW5kTjZSTQ==","stars.id":"ssc_7150b291c6b52a37","stars.type":"2","stars.flags":"5"},"name":"Apollo III Communications","id":"9","type":"url","url":"http:\/\/www.apollo3.com\/","sync_transaction_version":"1"}],"name":"Bookmarks bar","id":"1","type":"folder"},"sync_transaction_version":"5"}
key: other value: {"date_added":"13113606994595154","date_modified":"0","children":[],"name":"Other bookmarks","id":"2","type":"folder"}
key: date_added value: 13113606994595154
key: date_modified value: 0
key: children value: []
key: name value: Other bookmarks
key: id value: 2
key: type value: folder
key: synced value: {"date_added":"13113606994595157","date_modified":"0","children":[],"name":"Mobile bookmarks","id":"3","type":"folder"}
key: date_added value: 13113606994595157
key: date_modified value: 0
key: children value: []
key: name value: Mobile bookmarks
key: id value: 3
key: type value: folder
key: bookmark_bar value: {"date_added":"13113606994595146","date_modified":"13083379523340359","children":[{"date_added":"13081990058553125","meta_info":{"stars.id":"ssc_c257c6390425956c","stars.version":"sync.server.Chrome45"},"name":"Google","id":"7","type":"url","url":"https:\/\/www.google.com\/","sync_transaction_version":"1"},{"date_added":"13078166246742000","meta_info":{"stars.pageData":"Ig5keGVLcUJvcW5kTjZSTQ==","stars.id":"ssc_7150b291c6b52a37","stars.type":"2","stars.flags":"5"},"name":"Apollo III Communications","id":"9","type":"url","url":"http:\/\/www.apollo3.com\/","sync_transaction_version":"1"}],"name":"Bookmarks bar","id":"1","type":"folder"}
key: date_added value: 13113606994595146
key: date_modified value: 13083379523340359
key: children value: [{"date_added":"13081990058553125","meta_info":{"stars.id":"ssc_c257c6390425956c","stars.version":"sync.server.Chrome45"},"name":"Google","id":"7","type":"url","url":"https:\/\/www.google.com\/","sync_transaction_version":"1"},{"date_added":"13078166246742000","meta_info":{"stars.pageData":"Ig5keGVLcUJvcW5kTjZSTQ==","stars.id":"ssc_7150b291c6b52a37","stars.type":"2","stars.flags":"5"},"name":"Apollo III Communications","id":"9","type":"url","url":"http:\/\/www.apollo3.com\/","sync_transaction_version":"1"}]
key: name value: Bookmarks bar
key: id value: 1
key: type value: folder
key: sync_transaction_version value: 5
key: version value: 1

Update: This is an example of what I am trying to do, code from:
https://stackoverflow.com/a/40887240/1204365

import java.io.FileReader;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class Bookmark {

    private static String jsonFile = "/home/users/l/j/ljames/.config/google-chrome/Default/Bookmarks";

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        FileReader reader = new FileReader(jsonFile); // access the file

        JSONObject jsonObject = (JSONObject) new JSONParser().parse(reader);
        String checksum = jsonObject.optString("checksum");

        // get root object
        JSONObject root = jsonObject.getJSONObject("roots");

        // get root bookmarks object from root
        JSONObject bookmarks = root.getJSONObject("bookmark_bar");

        // get root children array from bookmarks
        JSONArray childrens = bookmarks.getJSONArray("children");

        JSONObject temp;
        for (int i = 0; i < childrens.size(); i++) {
            // get object using index from childrens array
            temp = childrens.getJSONObject(i);

            // get url
            String url = temp.optString("url");
        }

    }

}

The output/errors are:

check: b8b257094128d165d7ccc70d0498cc87
Exception in thread "main" java.lang.ClassCastException: org.json.simple.JSONObject cannot be cast to org.json.simple.JSONArray
    at javaTools.JsonParser.main(JsonParser.java:27)

There are six red marks in Eclipse. They are on the lines below. The suggested fix for each line is the same as the first... (highlight in bold text):

Line 19: String checksum = jsonObject.optString("checksum");

Error:   Suggesting:

Change to 'toJSONString(..)'
Add cast to 'temp'
Rename in file (Ctrl+2 R)

This same suggestion is repleated for the other five red error marks.

Line 22: JSONObject root = jsonObject.getJSONObject("roots");

Line 25: JSONObject bookmarks = root.getJSONObject("bookmark_bar");

Line 28: JSONArray childrens = bookmarks.getJSONArray("children");

Line 33: temp = childrens.getJSONObject(i);

Line 36: String url = temp.optString("url");

Solution

  • The parsing all URL links required nested traversing mean there can be nested arrays inside arrays and object.

    Approach :

    1.) we will fetch all the keys inside root element and traverse them so first parse the object

    try {
        jsonObject = (JSONObject) new JSONParser().parse(reader);
    } catch (IOException | ParseException e) {
        e.printStackTrace();
    }
    
    • Then fetch all the keys from required parent element i.e. root and traverse them using foreachloop.

      JSONObject root = (JSONObject) jsonObject.get("roots");
      // fetch all keys using keyset
      Set<String> set = root.keySet();
      // traverse all keys using foreach loop
      for (String string : set) {
      

    2.) While traversing we simply try to convert key as jsonobject and if key simply is a string inside our json file then exception will be raised string cannot be converted to JSONObject but will be catched so don't worry

        for (String string : set) {
            try {
                obj = (JSONObject) root.get(string);
            } catch (ClassCastException e) {
              // no need to do anything here
            }
        }
    

    3.) If it's a JSONObject then we simply try to find the children array which actually contains our urls links

        if (obj.containsKey("children")) {
            try {
                childrens = (JSONArray) obj.get("children");
    
                // call to recursive function to find nested children array 
                //and print url
                printUrls(childrens);
            } catch (Exception e) {
              // try-catch to handle any unexpected case
             }
        }
    

    4.) Now the nested array part , since any children can contain nested children arrays so i applied the concept of recursion to find and fetch content of nested arrays

    public static void printUrls(JSONArray childrens) {
        JSONObject temp = null;
        for (int i = 0; i < childrens.size(); i++) {
            // get object using index from children array
            temp = (JSONObject) childrens.get(i);
    
            // check if it contains any nested children array key
            // if yes then , fetch the nested children array and call this funtion
            // again to print it's content 
            if (temp.containsKey("children")) {
                printUrls((JSONArray) temp.get("children"));
            }
    
            // fetch and print the url , most wanted guy here
            String url = (String) temp.get("url");
            if (url != null) {
    
                // display the url using print 
                System.out.println(url);
    
                // count is a variable which will be incremented when any url found
                // and total of found urls , will be displayed at the end of parsing 
                count++;
            }
        }
    }
    

    Org.JSON jar link : click download jar option in the link and/or add it as a dependency jar in your project


    Code

    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.Objects;
    import java.util.Optional;
    import java.util.Set;
    
    import org.json.simple.JSONArray;
    import org.json.simple.JSONObject;
    import org.json.simple.parser.JSONParser;
    import org.json.simple.parser.ParseException;
    
    // parsing code using json.simple  
    public class Test2 {
    
        // path to your file 
        private static String jsonFile = "C:\\bookmarks.json";
        static int count = 0;
    
        public static void main(String[] args) {
    
            // a file reader class to access the file using string file path 
            FileReader reader = null;
            try {
                reader = new FileReader(jsonFile);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } // access the file
            JSONObject jsonObject = null;
    
            try {
                jsonObject = (JSONObject) new JSONParser().parse(reader);
            } catch (IOException | ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String checksum = (String) jsonObject.get("checksum");
    
            JSONObject root = (JSONObject) jsonObject.get("roots");
    
            Set<String> set = root.keySet();
            JSONArray childrens = null;
            JSONObject obj = null;
            for (String string : set) {
                try {
                    obj = (JSONObject) root.get(string);
                } catch (ClassCastException e) {
    
                }
                if (obj.containsKey("children")) {
                    try {
                        childrens = (JSONArray) obj.get("children");
                        printUrls(childrens);
                    } catch (Exception e) {
    
                    }
                }
            }
            // display , how many urls we have found  
            System.out.println("count is " + count);
        }
    
        public static void printUrls(JSONArray childrens) {
            JSONObject temp = null;
            for (int i = 0; i < childrens.size(); i++) {
                // get object using index from childrens array
                temp = (JSONObject) childrens.get(i);
                if (temp.containsKey("children")) {
                    printUrls((JSONArray) temp.get("children"));
                }
                // get url
                String url = (String) temp.get("url");
                if (url != null) {
                    System.out.println(url);
                    count++;
                }
            }
    
        }
    }
    

    Output : The link provided by OP has 2521 urls so can't post all but count value should be enough

    ...
    http://www.team-cymru.org/bogon-reference-http.html
    http://www.team-cymru.org/bogon-reference-bgp.html
    http://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt
    http://tecadmin.net/enable-logging-in-iptables-on-linux/#
    https://www.youtube.com/watch?v=geglU1AdmJs&t=480s
    count is 2521