jsonpowershellgoogle-chromebookmarkspowershell-5.0

Export Chrome Bookmarks to CSV file using PowerShell


I am trying to export the Chrome Bookmarks to CSV/Excel using Powershell. I am hitting at a barrier with regard to an incorrect JSON file being created. This is due to two sets of folders in Chrome called Bookmark_Bar and Synced.

The BookMark_Bar creates a JSON with a brackets as below:

[
{

},
{

}
]

The Synced Folder also creates a set of data as below in the same file:

[
{

},
{

}
]

The code is as below.

$isodate = Get-Date -Format yyyymmmdd_hhmmss
$logFilePath = "d:\PowerShell_$isodate.log"
# ############################
Start-Transcript -Path $logFilePath -Append
#########################################

#Declare Variables

$pathToJsonFile = "$env:localappdata\Google\Chrome\User Data\Default\Bookmarks"
#$JsonFilePath = "D:\04. PowerShell\BookMarks\ChromeBookMarx.json"
#$OutputFilePath = "D:\BookMarx.csv" 

$data = Get-content $pathToJsonFile | out-string | ConvertFrom-Json

Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"


#A nested function to enumerate bookmark folders
Function Get-BookmarkFolder {
[cmdletbinding()]
Param(
[Parameter(Position=0,ValueFromPipeline=$True)]
$Node
)

Process 
{

 foreach ($child in $node.children) 
 {
   #get parent folder name
   $parent = $node.Name
   if ($child.type -eq 'Folder') 
   {
     Write-Verbose "Processing $($child.Name)"
     Get-BookmarkFolder $child
   }
   else 
   {
        $hash= [ordered]@{
          Folder = $parent
          Name = $child.name
          URL = $child.url
          Added = [datetime]::FromFileTime(([double]$child.Date_Added)*10)
        }
      #write custom object
        New-Object -TypeName PSobject -Property $hash
  } #else url
 } #foreach
 } #process
} #end function

#create a new JSON file
$text | Set-Content 'file.json'
$test1 = '{
  "markers":' | Add-Content 'file.json'

#these should be the top level "folders"
$data.roots.bookmark_bar | Get-BookmarkFolder |ConvertTo-Json |Add-Content 'D:\file.json'
$data.roots.other | Get-BookmarkFolder  |ConvertTo-Json |Add-Content 'D:\file.json'
$data.roots.synced | Get-BookmarkFolder  |ConvertTo-Json |Add-Content 'D:\file.json'

$EndBraceClose = ']}' | Add-Content 'file.json'

Get-Content 'D:\file.json' -Raw |
ConvertFrom-Json | select -ExpandProperty markers|
Export-CSV $env:USERPROFILE\desktop\ChromeBookMarx_$isodate.csv -NoTypeInformation

    # end logging 
    ###########################
    Stop-Transcript
    ###########################

The result of the JSON file is shown below: -

{
  "BookMarks":
[
    {
        "Folder":  "Sanddance",
        "Name":  "Microsoft Garage",
        "URL":  "https://www.microsoft.com/en-us/garage/workbench/",
        "Added":  "\/Date(1504585556230)\/"
    },
    {
        "Folder":  "Sanddance",
        "Name":  "Microsoft has a new data visualization tool you can use for free",
        "URL":  "https://thenextweb.com/",
        "Added":  "\/Date(1504584050296)\/"
    }
]
[
   {
        "Folder":  "Amazon",
        "Name":  "Cycling Equipment: Buy Cycling Accessories, Bike Tools \u0026 Equipment Online at Low Prices in India",
        "URL":  "https://www.amazon.in/",
        "Added":  "\/Date(1504859500323)\/"
    },

    {
        "Folder":  "Other bookmarks",
        "Name":  "Zakir Khan-Fan Honge Dusron Ke Apne To Dost Hote Hai - YouTube",
        "URL":  "https://www.youtube.com/watch?v=n4WKiwhn29o",
        "Added":  "\/Date(1497416694729)\/"
    }
]
]
}

The brackets on line 16 and 17 seems to be causing the problem. I need some help rectifying the code written.


Solution

  • If you have a look at the basic structure of a JSON Example, there are no [] http://json.org/example.html

    So i slightly adjusted your script also my path to chrome is different from yours so you'll have to change that.

        $isodate = Get-Date -Format yyyymmmdd_hhmmss
    $file = "C:\temp\file.json"
    #Declare Variables
    
    $pathToJsonFile = "$env:localappdata\Google\Chrome\User Data\Profile 1\Bookmarks"
    #$JsonFilePath = "D:\04. PowerShell\BookMarks\ChromeBookMarx.json"
    #$OutputFilePath = "D:\BookMarx.csv" 
    
    $data = Get-content $pathToJsonFile | out-string | ConvertFrom-Json
    
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"
    
    
    #A nested function to enumerate bookmark folders
    Function Get-BookmarkFolder {
    [cmdletbinding()]
    Param(
    [Parameter(Position=0,ValueFromPipeline=$True)]
    $Node
    )
    
    Process 
    {
    
     foreach ($child in $node.children) 
     {
       #get parent folder name
       $parent = $node.Name
       if ($child.type -eq 'Folder') 
       {
         Write-Verbose "Processing $($child.Name)"
         Get-BookmarkFolder $child
       }
       else 
       {
            $hash= [ordered]@{
              Folder = $parent
              Name = $child.name
              URL = $child.url
              Added = [datetime]::FromFileTime(([double]$child.Date_Added)*10)
            }
          #write custom object
            New-Object -TypeName PSobject -Property $hash
      } #else url
     } #foreach
     } #process
    } #end function
    
    #create a new JSON file
    $text | Set-Content $file -Force
    $test1 = '{
      "markers":' | Add-Content $file
    
    #these should be the top level "folders"
    $data.roots.bookmark_bar | Get-BookmarkFolder |ConvertTo-Json |Add-Content $file
    $data.roots.other | Get-BookmarkFolder  |ConvertTo-Json |Add-Content $file
    $data.roots.synced | Get-BookmarkFolder  |ConvertTo-Json |Add-Content $file
    
     '}' | Add-Content $file
    
    Get-Content $file -Raw |
    ConvertFrom-Json | select -ExpandProperty markers|
    Export-CSV $env:USERPROFILE\desktop\ChromeBookMarx_$isodate.csv -NoTypeInformation
    

    This gives me a working CSV file on my desktop. Fun idea btw.

    So this line was the biggest issue i found:

    $EndBraceClose = ']}' | Add-Content 'file.json'