MacOS – How to access the .plist with JXA (Javascript for Automation)

applescriptjavascript-automationmacos

According to the Script Dictionary:

PropertyListFile Object [inh. File] : A file containing data in
Property List format

properties:
(PropertyListItem) : the contents of the property list file;
elements and properties of the property list item may be accessed
as if they were elements and properties of the property list file

and in Apple's JavaScript for Automation Release Notes

… the returned object is an object specifier —
a reference to the accessed property—rather than the actual value.
To send the get event to the external entity and return its value,
call the property as a function:

But I don't know how to correctly use the object specifiers I am returned, nor can I see how to provide the particular plistPath to the PropertyListFile. Here's what I tried:

let app = Application.currentApplication()
app.includeStandardAdditions = true

let systemEvents = Application("System Events")
let plistPath = Path("/Users/iain/testing.plist")
let cats = systemEvents.PropertyListFile(plistPath).catsList

console.log(cats)     /* --> undefined */

I am trying to emulate the Applescript:

to getCats()

    tell application "System Events"

        tell property list file plistPath
            set availableCategories to value of property list item "catsList"
        end tell

    end tell

end getCats

This is the .plist file:

√ nodejxa % cat ~/testing.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>blogPath</key>
    <string>/Users/iain/WebDev/iainhouston.github.io/_posts/</string>
    <key>catsList</key>
    <array>
        <string>Blog</string>
        <string>Devops</string>
        <string>Drupal</string>
        <string>Formal Methods</string>
        <string>Parish Councils</string>
        <string>Scripting</string>
    </array>
    <key>scriptFilePath</key>
    <string>/Users/iain/bin/makepost.py</string>
</dict>
</plist>

Best Answer

I just had to figure out how to open and read a plist with JXA myself, and it was not intuitive at all. The documentation on JXA is frankly terrible. I searched the dictionaries in Script Editor, but also made liberal use of the properties() method in Script Editor, which will show you all the properties of many objects.

I finally did figure it out for myself, and I think this will work for you:

let app = Application.currentApplication()
app.includeStandardAdditions = true

let systemEvents = Application("System Events")
let cats = systemEvents.propertyListFiles.byName("/Users/iain/testing.plist").contents.value()['catsList'];

Results in the log:

/* Blog,Devops,Drupal,Formal Methods,Parish Councils,Scripting */
Related Question