如何使用 AppleScript 从 JSON 文件中获取值?

How to get values from JSON file using AppleScript?

关于这个问题,

如何从如下所示的 JSON 文件中获取值,

["AA-BB-CC-MAKE-SAME.json","SS-ED-SIXSIX-TENSE.json","FF-EE-EE-EE-WW.json","ZS-WE-AS-FOUR-MINE.json","DD-RF-LATERS-LATER.json","FG-ER-DC-ED-FG.json"]

在 MAC 中使用 AppleScript OS?

这是Hackoo,

提供的Windows中的部分VBScript代码
strJson = http.responseText
Result = Extract(strJson,"(\x22(.*)\x22)")
Arr = Split(Result,",")
For each Item in Arr
    wscript.echo Item
Next
'******************************************
Function Extract(Data,Pattern)
   Dim oRE,oMatches,Match,Line
   set oRE = New RegExp
   oRE.IgnoreCase = True
   oRE.Global = True
   oRE.Pattern = Pattern
   set oMatches = oRE.Execute(Data)
   If not isEmpty(oMatches) then
       For Each Match in oMatches  
           Line = Line & Trim(Match.Value) & vbCrlf
       Next
       Extract = Line
   End if
End Function
'******************************************

在 MAC OS AppleScript 中,我只需要将 JSON 文件的值获取到单个字符串值数组的代码。上面显示的 VBScript 示例是 JSON 文件内容的样子。

How to get the values from JSON file that looks like this,

["AA-BB-CC-MAKE-SAME.json","SS-ED-SIXSIX-TENSE.json","FF-EE-EE-EE-WW.json","ZS-WE-AS-FOUR-MINE.json","DD-RF-LATERS-LATER.json","FG-ER-DC-ED-FG.json"]

如果您的意思是您所写的,并且 JSON 文件的内容是单个数组中六个字符串的列表,在一行中格式化,最简单的方法是将其视为文本,trim 打开和关闭方括号,然后在每次出现 , 时分隔其字段。最后,每个单独的文本项也可以有周围的引号 trimmed。

检查 VBScript,它看起来使用了一个非常相似的过程,尽管使用了正则表达式,AppleScript 没有提供正则表达式,但在这种简单情况下并不是特别必要。

假设上面的 JSON 数组存储在桌面上名为“myfile.json”的文件中。那么:

    set home to the path to home folder
    set f to the POSIX path of home & "Desktop/myfile.json"
    
    set JSONstr to read POSIX file f
    
    # Trim square brackets
    set JSONstr to text 2 thru -2 of JSONstr
    
    # Delimit text fields using comma
    set the text item delimiters to ","
    set Arr to the text items of JSONstr
    
    # Trim quotes of each item in Arr
    repeat with a in Arr
        set contents of a to text 2 thru -2 of a
    end repeat
    
    # The final array
    Arr

I only need the code to get the values of the JSON file to a single array of string values. The above shown example above the VBScript is the how JSON file contents looks like.

变量 Arr 现在包含字符串值数组(在 AppleScript 中称为 lists)。您可以像这样访问其中的特定项目:

    item 2 of Arr --> "SS-ED-SIXSIX-TENSE.json"

更通用的解决方案

我决定在 AppleScript 中包含一种更高级的方法来处理 JSON,部分原因是我最近一直在做很多 JSON 处理,而且这一切都是新鲜的我的事件视界;还要证明,使用 AppleScriptObjC,不仅可以解析非常复杂的 JSON 数据,而且非常简单。

我认为您在这种特定情况下不需要它,但它可能会在未来的某些情况下派上用场。

该脚本分为三个部分:它开始导入赋予 AppleScript 额外权力的相关 Objective-C 框架;然后,我定义了实际的处理程序本身,称为 JSONtoRecord,我将在下面进行描述。最后,是脚本的底部,您可以在其中输入代码并随心所欲地使用它:

    use framework "Foundation"
    use scripting additions
    --------------------------------------------------------------------------------
    property ca : a reference to current application
    property NSData : a reference to ca's NSData
    property NSDictionary : a reference to ca's NSDictionary
    property NSJSONSerialization : a reference to ca's NSJSONSerialization
    property NSString : a reference to ca's NSString
    property NSUTF8StringEncoding : a reference to 4
    --------------------------------------------------------------------------------
    on JSONtoRecord from fp
        local fp
        
        set JSONdata to NSData's dataWithContentsOfFile:fp
        
        set [x, E] to (NSJSONSerialization's ¬
            JSONObjectWithData:JSONdata ¬
                options:0 ¬
                |error|:(reference))
        
        if E ≠ missing value then error E
        
        tell x to if its isKindOfClass:NSDictionary then ¬
            return it as record
        
        x as list
    end JSONtoRecord
    --------------------------------------------------------------------------------
    ###YOUR CODE BELOW HERE
    #
    #
    set home to the path to home folder
    set f to the POSIX path of home & "Desktop/myfile.json"
    
    JSONtoRecord from f
    
    --> {"AA-BB-CC-MAKE-SAME.json", "SS-ED-SIXSIX-TENSE.json", ¬
    --> "FF-EE-EE-EE-WW.json", "ZS-WE-AS-FOUR-MINE.json", ¬
    --> "DD-RF-LATERS-LATER.json", "FG-ER-DC-ED-FG.json"}

在脚本的底部,我调用了 JSONtoRecord 处理程序,将 myfile.json 的位置传递给它。此处理程序的好处之一是,无论文件是在一行上格式化还是在多行上格式化都无关紧要。它还可以处理复杂的嵌套 JSON 数组。

在这些情况下,它 returns 是原生 AppleScript record 对象,所有 JSON 变量都存储为记录中的 属性 值。然后访问变量变得非常简单。

这实际上正是一些人已经提到的 JSON Helper 应用程序在幕后所做的事情。

一个标准(除了包含有效 JSON 数据的 JSON 文件外)是文件的路径是完整写入的 posix 路径,例如/Users/CK/Desktop/myfile.json不是 ~/Desktop/myfile.json,甚至更糟,Macintosh HD:Users:CK:Desktop:myfile.json

简短回答: 不幸的是,AppleScript 不提供解析 JSON 的内置功能,这类似于 JavaScript 的 JSON.parse()方法。

以下是几个解决方案:

  • 解决方案一:需要安装第三方插件,不一定可行。
  • 解决方案2:不需要安装任何第三方插件,而是使用macOS内置的tools/features作为标准。

解决方案 1:

如果您有能力在您的用户系统上安装第三方插件,那么您可以安装 JSON Helper for AppleScript (正如@user3439894 在评论中所建议的那样).

然后在您的 AppleScript 中使用它,如下所示:

set srcJson to read POSIX file (POSIX path of (path to home folder) & "Desktop/foobar.json")
tell application "JSON Helper" to set myList to read JSON from srcJson

解释:

  1. 第 1 行,我们读取 .json 文件的内容并将其分配给名为 srcJson 的变量。

    注意您需要根据需要更改路径部分(即Desktop/foobar.json)。

  2. 第 2 行 我们使用 JSON Helper 插件解析内容。这会将源 JSON 数组的每个项目分配给新的 AppleScript list。生成的 AppleScript list 被分配给名为 myList.

  3. 的变量

解决方案 2:

通过使用 macOS 内置的标准工具,您还可以通过 AppleScript 执行以下操作。这假设您的 JSON 文件是 valid 并且仅包含一个数组:

set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
set myList to text items of (do shell script "tr ''\\n\\r''  ' ' <~/Desktop/foobar.json | sed 's/^ *\[ *\"//; s/ *\" *\] *$//; s/\" *, *\"/,/g;'")
set AppleScript's text item delimiters to TID

注意:您需要根据需要更改路径部分(即~/Desktop/foobar.json)。

此外,如果您的 .json 文件名包含 space(s),您需要使用 \ 对它们进行转义。例如~/Desktop/foo\ bar.json

解释:

  1. 第 1 行 AppleScript 的当前 text item delimiters 被分配给名为 TID.

    [=191 的变量=]
  2. 第 2 行 AppleScript's text item delimiters 设置为逗号 - 这有助于从源 JSON 中提取每个单独的值数组并将每个值分配给新的 AppleScript list.

  3. 第3行一个shell脚本通过do shell script命令执行,执行以下操作:

    • 通过读取~/Desktop/foobar.json的部分读取源.json文件的内容。此路径当前假定文件名为 foobar.json 并位于您的 Desktop 文件夹中 (您需要将此路径更改为实际文件所在的位置)

    • foobar.json 的内容被重定向,(注意文件路径前的 <),到 tr(即读取的部分:tr ''\\n\\r'' ' ').此翻译将用 space 字符替换源 .json 数组内容中可能存在的任何换行符。这确保 foobar.json 的内容转换为一行。

      注意:JSON 数组可以在每个项目之间包含换行符并且仍然有效,因此尽管您问题中给出的示例 JSON 出现在一行 - 这不是此解决方案的要求,因为它也可以处理多行。

    • 然后将一行文本通过管道传输到 seds command 进行进一步处理(即读取的部分:| sed 's/^ *\[ *\"//; s/ *\" *\] *$//; s/\" *, *\"/,/g;')。

      The syntax of the s command is 's/regexp/replacement/flags'.

      让我们分解每个 s 命令以进一步了解发生了什么:

      • s/^ *\[ *\"// 删除左方括号 [,其前面或后面可能有零个或多个 space 字符,以及从字符串开头开始的以下双引号(即第一次出现)。

      • s/ *\" *\] *$// 删除右方括号 ],其前面或后面可能有零个或多个 space 字符,以及字符串末尾的前面的双引号(即最后一次出现)。

      • s/\" *, *\"/,/g 替换单个逗号,(前面可以有零个或多个 space,and/or后跟零个或多个 spaces) 和一个逗号。

    • 第 3 行 的开头部分是这样的; set myList to text items of ... 利用 text items 将字符串读入 AppleScript list,使用逗号作为分隔符来确定 list 的每个项目。结果数组分配给名为 myList.

    • 的变量
  4. 第4行 AppleScript's text item delimiters恢复到原来的值。

为源 JSON 文件路径使用变量。

如果你想使用一个变量作为源 .json 文件的文件路径,那么你可以这样做:

set srcFilePath to quoted form of (POSIX path of (path to home folder) & "Desktop/foobar.json")

set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
set myList to text items of (do shell script "tr ''\\n\\r'' ' ' <" & srcFilePath & " | sed 's/^ *\[ *\"//; s/ *\" *\] *$//; s/\" *, *\"/,/g;'")
set AppleScript's text item delimiters to TID

注意这与第一个例子非常相似。显着差异是:

  • 在第一行,我们将文件路径分配给名为 srcFilePath 的变量。
  • do shell script 中我们引用 srcFilePath 变量。

关于 JSON 转义特殊字符的补充说明: 解决方案 2 保留任何 JSON escaped special characters 可能出现在 source JSON 数组的值中。但是,解决方案 1 将解释它们。

注意事项 解决方案 2 在源 JSON 数组中的项目包含逗号时产生意外结果,因为逗号是用作 text item delimiters.