Wednesday, July 18, 2018

#1 2014-05-04 06:03:58 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5409

Property lists, JSON and AppleScript

A discussion came up elsewhere about converting between AppleScript/JSON/property lists, so I've written an ASObjC-based library for it. It requires Mavericks, and you can read about how to add a library elsewhere here.

Applescript:

use framework "Foundation"

-- pass a string, list, record or number, and either a path to save the result to, or missing value to have it returned as text
on convertASToJSON:someASThing saveTo:posixPath
   --convert to JSON data
   set {theData, theError} to current application's NSJSONSerialization's dataWithJSONObject:someASThing options:0 |error|:(reference)
   if theData is missing value then error (theError's localizedDescription() as text) number -10000
   if posixPath is missing value then -- return string
       -- convert data to a UTF8 string
       set someString to current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)
       return someString as text
   else
       -- write data to file
       theData's writeToFile:posixPath atomically:true
       return result as boolean -- returns false if save failed
   end if
end convertASToJSON:saveTo:

-- pass either a POSIX path to the JSON file, or a JSON string; isPath is a boolean value to tell which
on convertJSONToAS:jsonStringOrPath isPath:isPath
   if isPath then -- read file as data
       set theData to current application's NSData's dataWithContentsOfFile:jsonStringOrPath
   else -- it's a string, convert to data
       set aString to current application's NSString's stringWithString:jsonStringOrPath
       set theData to aString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
   end if
   -- convert to Cocoa object
   set {theThing, theError} to current application's NSJSONSerialization's JSONObjectWithData:theData options:0 |error|:(reference)
   if theThing is missing value then error (theError's localizedDescription() as text) number -10000
   -- we don't know the class of theThing for coercion, so...
   if (theThing's isKindOfClass:(current application's NSArray)) as integer = 1 then
       return theThing as list
   else
       return item 1 of (theThing as list)
   end if
end convertJSONToAS:isPath:

-- pass a string, list, record or number, and either a path to save the result to, or missing value to have it returned as text
on convertASToPlist:someASThing saveTo:posixPath
   if posixPath is missing value then -- return string
       -- convert to property list data
       set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:someASThing format:(current application's NSPropertyListXMLFormat_v1_0) options:0 |error|:(reference) -- don't use binary format
       if theData is missing value then error (theError's localizedDescription() as text) number -10000
       -- convert data to UTF8 string
       set someString to current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)
       return someString as text
   else -- saving to file
       -- convert to property list data
       set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:someASThing format:(current application's NSPropertyListBinaryFormat_v1_0) options:0 |error|:(reference) -- might as well use binary format
       if theData is missing value then error (theError's localizedDescription() as text) number -10000
       -- write data to file
       theData's writeToFile:posixPath atomically:true
       return result as boolean -- returns false if save failed
   end if
end convertASToPlist:saveTo:

-- pass either a POSIX path to the .plist file, or a property list string; isPath is a boolean value to tell which
on convertPlistToAS:plistStringOrPath isPath:isPath
   if isPath then -- read file as data
       set theData to current application's NSData's dataWithContentsOfFile:plistStringOrPath
   else -- it's a string, convert to data
       set aString to current application's NSString's stringWithString:plistStringOrPath
       set theData to aString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
   end if
   -- convert to Cocoa object
   set {theThing, theError} to current application's NSPropertyListSerialization's propertyListWithData:theData options:0 format:(missing value) |error|:(reference)
   if theThing is missing value then error (theError's localizedDescription() as text) number -10000
   -- we don't know the class of theThing for coercion, so...
   if (theThing's isKindOfClass:(current application's NSArray)) as integer = 1 then
       return theThing as list
   else
       return item 1 of (theThing as list)
   end if
end convertPlistToAS:isPath:

-- pass either a POSIX path to the JSON file, or a JSON string; isPath is a boolean value to tell which. saveTo is either a path to save the result to, or missing value to have it returned as text
on convertJSONToPlist:jsonStringOrPath isPath:isPath saveTo:posixPath
   if isPath then -- read file as data
       set theData to current application's NSData's dataWithContentsOfFile:jsonStringOrPath
   else -- it's a string, convert to data
       set aString to current application's NSString's stringWithString:jsonStringOrPath
       set theData to aString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
   end if
   -- convert to Cocoa object
   set {theThing, theError} to current application's NSJSONSerialization's JSONObjectWithData:theData options:0 |error|:(reference)
   if theThing is missing value then error (theError's localizedDescription() as text) number -10000
   if posixPath is missing value then -- return string
       -- convert to property list data
       set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:theThing format:(current application's NSPropertyListXMLFormat_v1_0) options:0 |error|:(reference) -- don't use binary format
       if theData is missing value then error (theError's localizedDescription() as text) number -10000
       -- convert data to UTF8 string
       set someString to current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)
       return someString as text
   else -- saving to file
       -- convert to property list data
       set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:theThing format:(current application's NSPropertyListBinaryFormat_v1_0) options:0 |error|:(reference) -- might as well use binary format
       if theData is missing value then error (theError's localizedDescription() as text) number -10000
       -- write data to file
       theData's writeToFile:posixPath atomically:true
       return result as boolean -- returns false if save failed
   end if
end convertJSONToPlist:isPath:saveTo:

-- pass either a POSIX path to the .plist file, or a property list string; isPath is a boolean value to tell which. saveTo is either a path to save the result to, or missing value to have it returned as text
on convertPlistToJSON:plistStringOrPath isPath:isPath saveTo:posixPath
   if isPath then -- read file as data
       set theData to current application's NSData's dataWithContentsOfFile:plistStringOrPath
   else -- it's a string, convert to data
       set aString to current application's NSString's stringWithString:plistStringOrPath
       set theData to aString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
   end if
   -- convert to Cocoa object
   set {theThing, theError} to current application's NSPropertyListSerialization's propertyListWithData:theData options:0 format:(missing value) |error|:(reference)
   if theThing is missing value then error (theError's localizedDescription() as text) number -10000
   --convert to JSON data
   set {theData, theError} to current application's NSJSONSerialization's dataWithJSONObject:theThing options:0 |error|:(reference)
   if theData is missing value then error (theError's localizedDescription() as text) number -10000
   if posixPath is missing value then -- return string
       -- convert data to a UTF8 string
       set someString to current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)
       return someString as text
   else
       -- write data to file
       theData's writeToFile:posixPath atomically:true
       return result as boolean -- returns false if save failed    
   end if
end convertPlistToJSON:isPath:saveTo:

Here's a simple example of calling the handlers:

Applescript:

set theValue to {x:2, y:3, z:{4, 5, "abc"}}
tell script "^"
   set theJSON to its convertASToJSON:theValue saveTo:(missing value)
   log theJSON
   set theAS to its convertJSONToAS:theJSON isPath:false
   log theAS
   set thePlist to its convertASToPlist:theValue saveTo:(missing value)
   log thePlist
   set theAS to its convertPlistToAS:thePlist isPath:false
   log theAS
   set thePlist to its convertJSONToPlist:theJSON isPath:false saveTo:(missing value)
   log thePlist
   set theJSON to its convertPlistToJSON:thePlist isPath:false saveTo:(missing value)
   log theJSON
end tell


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#2 2014-05-05 04:36:37 am

DJ Bazzie Wazzie
Member
From:: the Netherlands
Registered: 2004-10-20
Posts: 2776
Website

Re: Property lists, JSON and AppleScript

cool

Online

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)