AppleScript で JSON を利用する

AppleScript なら JSON を簡単に利用できます。

そう、Marvericks ならね。

...冗談はさておき。最近では JSON でデータの交換ってことが多くなってきて、時代から置いてきぼりな感がある AppleScript です。JSON を AppleScript で利用できるようにする方法は既に幾つかあります。

前者は OSAX として提供されており、後者は AppleScript で解決するスクリプトです。

他方、OS X と iOS には NSJSONSerialization という JSON を扱うためのクラスが少し前から追加されています。このクラスを利用すれば AppleScript のリストやレコードを JSON に、逆に JSON を AppleScript のリストやレコードに変換することができます。

まず、NSJSONSerialization を利用するライブラリを作ります。

Script Editor で開く

property NSString : class "NSString"
property NSData : class "NSData"
property NSJSONSerialization : class "NSJSONSerialization"
property NSArray : class "NSArray"
property NSDictionary : class "NSDictionary"

on serialize(theText)
    -- AppleScript 文字列を NSString に変換
    set theText to NSString's stringWithString:theText
    -- NSString を NSData に変換
    set jsonData to theText's dataUsingEncoding:(current application's NSUnicodeStringEncoding)

    -- NSData に変換した JSON を パース
    set theResult to NSJSONSerialization's JSONObjectWithData:jsonData options:(current application's NSJSONReadingAllowFragments) |error|:(missing value)

    -- NSArray か NSDictionary で結果が返ってくる
    if (theResult's isKindOfClass:(NSDictionary's |class|)) as boolean then
        -- NSDictionary なら record に型変換
        return theResult as record
    else
        return theResult as list
    end if
end serialize

on deserialize(theObject)
    -- 渡されたデータが list か record か判別
    if (class of theObject) is list then
        -- list から NSArray に変換
        set theObject to NSArray's arrayWithArray:theObject
    else
        set theObject to NSDictionary's dictionaryWithDictionary:theObject
    end if

    if (NSJSONSerialization's isValidJSONObject:theObject) then
        -- JSON に変換できるなら
        set json to NSJSONSerialization's dataWithJSONObject:theObject options:(current application's NSJSONWritingPrettyPrinted) |error|:(missing value)
        -- 変換された NSData から NSString に変換
        set theText to NSString's alloc()'s initWithData:json encoding:(current application's NSUTF8StringEncoding)

        -- NSString を text に変換
        return theText as text
    else
        return missing value
    end if
end deserialize

このスクリプトをライブラリとして保存します(ライブラリとして保存する方法はこちらを参照)。

使い方はいたって簡単。

Script Editor で開く

-- record、list まじりの list
set theList to {"a", "b", {10, 20}, {age:20}}
tell script "ASJSON" to set json to deserialize(theList)
--> 結果
"[
  \"a\",
  \"b\",
  [
    10,
    20
  ],
  {
    \"age\" : 20
  }
]"

-- record 
set theRecord to {a:100, b:200, c:{10, 20}}
tell script "ASJSON" to set json to deserialize(theRecord)
--> 結果  
"{
  \"a\" : 100,
  \"b\" : 200,
  \"c\" : [
    10,
    20
 ]
}"

--> JSON を変換してみる
"{
  \"a\" : 100,
  \"b\" : 200,
  \"c\" : [
    10,
    20
  ],
  \"d\" : null,
  \"e\" : false,  
  \"f\" : 0.13
}"

set json to result
tell script "ASJSON" to set json to serialize(json)
--> 実数の値が...
--> {d:missing value, b:200, e:false, c:{10, 20}, a:100, f:0.129999995232}

実数の取り扱いに難があるものの、きれいに変換できます。実際の利用となると、エラーの処理(パースできなかったとき等)が必要になるものの、これで Web API を利用した AppleScript がより身近になりますね。