AppleScript to import fields from json file

Users asking other users for AppleScripts that work with Bookends.
Post Reply
tikkari
Posts: 1
Joined: Mon Nov 18, 2024 8:37 am

AppleScript to import fields from json file

Post by tikkari »

Just bought Bookends and learning to use it. Copied articles into Bookends library, but I would like to add abstracts from json file (made with python script from old ref.manager library).

So, I have json file with "doi" and "abstract" fields. I think I should use DOIs as a key identifiers, and if DOIs match (in json file and in existing Bookends library), then add abstract into text field, if its empty.

As I am not familiar with AppleScript, no success with this, and those AI services could not help either :( ... It seems the looping and field recognition is not working with my code properly. Is there a better way to do this or should I continue with my AppleScript?

I would like to use something like this, as I would later use keyword import as well (created with some ML).

Thanks!

edit: The actual question is, is this doable - I can add my scripts if this still is "the right direction".
DrJJWMac
Posts: 379
Joined: Sat Jun 22, 2019 8:04 am
Location: Alabama USA

Re: AppleScript to import fields from json file

Post by DrJJWMac »

It is doable. The major steps are

* read the JSON into a property type list --> look for AppleScripts that are already designed to do this
* find a DOI from the property list in the references
* attach the abstract

The second task would ultimately be better code that supports the equivalent syntax: for-each(where DOIsource == DOIreference) do ... types of iteration. XML comes to mind.

Perhaps you can have an easier time to do this ...

* Export the DOI list and ABSTRACT field from (selected or all) references in the library --> no AppleScript needed, just export from within BE
* Use an external code method to process the DOI list from BE against the JSON DOI list to cull to references that need abstracts
* If the list is short enough, replace by hand ... otherwise ... write an AppleScript to replace only those cases where the abstract is empty
--
JJW
msteffens
Posts: 41
Joined: Thu Jul 19, 2007 10:04 am
Location: Germany
Contact:

Re: AppleScript to import fields from json file

Post by msteffens »

tikkari wrote: Mon Nov 18, 2024 10:06 am Just bought Bookends and learning to use it. Copied articles into Bookends library, but I would like to add abstracts from json file
As JJW notes, it should be doable. Would it be possible for you to upload your JSON file somewhere, or at least post a representative sample?
msteffens
Posts: 41
Joined: Thu Jul 19, 2007 10:04 am
Location: Germany
Contact:

Re: AppleScript to import fields from json file

Post by msteffens »

I'm not sure if tikkari is still looking for a solution but since others may be looking for something similar, I'm posting an AppleScript solution below.

The below script will ask you to choose a .json file (which must contain an array of dictionaries with "doi" and "abstract" key/value pairs). It will then parse your chosen .json file and find publications with matching DOIs in your frontmost Bookends library. All matching publications with empty abstract fields will get updated so that they contain the abstracts from the .json file.

If the structure of your .json file is different, you'd obviously need to adopt the script accordingly.

Code: Select all

-- Adds abstracts from a .json file to Bookends publications with matching DOIs.

-- by Matthias Steffens, keypoints.app

-- This script expects a .json file with JSON data like this:
(*
[
    {
        "doi": "<DOI>",
        "abstract": "<ABSTRACT>"
    },
    {
        "doi": "<DOI>",
        "abstract": "<ABSTRACT>"
    }
]
*)
-- In the above JSON sample, the <DOI> and <ABSTRACT> placeholders would
-- need to be replaced with your actual metadata.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property processedPubs : {}
property changedPubs : {}

-- main handler
on run
	-- set theFile to POSIX file "/Users/someuser/folder/file.json"
	set theFile to choose file with prompt ¬
		"Choose the .json file containing your publication metadata:" of type {"public.json"} ¬
		without multiple selections allowed
	
	set pubMetadata to my parseJSONFromFile(theFile)
	if pubMetadata is not missing value and pubMetadata is not {} then my processPublicationMetadata(pubMetadata)
	
	tell application "Bookends"
		display dialog "Processed publications: " & (count of processedPubs) & ¬
			linefeed & "Added abstracts: " & (count of changedPubs) ¬
			with title "Finished Adding Abstracts to Publications" with icon 1 buttons {"OK"} default button "OK"
	end tell
	
end run

-- Iterates over the given list of publication metadata records (which each contain `doi` & `abstract`
-- key/value pairs) and updates the abstract field of Bookends publications with matching DOIs.
on processPublicationMetadata(pubMetadata)
	if pubMetadata is {} then return
	
	repeat with pubMetadataEntry in pubMetadata
		set foundPubs to my publicationsWithDOI(pubMetadataEntry's doi)
		if foundPubs is not {} then
			set processedPubs to processedPubs & foundPubs
			
			repeat with aPub in foundPubs
				set didChangePub to my addAbstractForPublication(pubMetadataEntry's abstract, aPub)
				if didChangePub is true then set changedPubs to changedPubs & {aPub}
			end repeat
		end if
	end repeat
end processPublicationMetadata

-- Returns all publications from the frontmost Bookends database whose DOI matches
-- the given DOI. Returns an empty list if no matching publications were found.
on publicationsWithDOI(theDOI)
	if theDOI is "" or theDOI is missing value then return {}
	
	tell application "Bookends"
		tell front library window
			set foundPubs to (every publication item whose doi is theDOI)
		end tell
	end tell
	
	return foundPubs
end publicationsWithDOI

-- Copies the given text to the abstract field of the given Bookends publication. Does nothing
-- if the publication's abstract field already contains some text.
on addAbstractForPublication(theAbstract, thePub)
	if theAbstract is "" or theAbstract is missing value then return missing value
	if thePub is missing value then return missing value
	
	tell application "Bookends"
		tell front library window
			if thePub's abstract is "" then
				set thePub's abstract to theAbstract
				return true
			end if
		end tell
	end tell
	
	return false
end addAbstractForPublication

-- Reads JSON data from the given .json file and returns the JSON data as a record
-- or a list. Returns missing value if the JSON data could not be parsed successfully.
-- Credits: modified after script code by users alldritt, ComplexPoint & ShaneStanley @ https://forum.latenightsw.com/t/reading-json-data-with-nsjsonserialization/958
on parseJSONFromFile(jsonFile)
	if jsonFile is missing value then return {}
	
	set theJSONData to current application's NSData's dataWithContentsOfFile:(jsonFile's POSIX path)
	set {theJSON, parseError} to current application's NSJSONSerialization's JSONObjectWithData:theJSONData options:0 |error|:(reference)
	
	if theJSON is missing value then
		return missing value
	else if theJSON's isKindOfClass:(current application's NSDictionary) then
		return theJSON as record
	else
		return theJSON as list
	end if
end parseJSONFromFile
Post Reply