【问题标题】:How to get values from JSON file using AppleScript?如何使用 AppleScript 从 JSON 文件中获取值?
【发布时间】:2018-08-06 21:44:41
【问题描述】:

关于这个问题,

How to download and get values from JSON file using VBScript or batch file?

如何从如下所示的 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?

这是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 文件内容的样子。

【问题讨论】:

标签: json macos applescript


【解决方案1】:

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

以下是几个解决方案:

  • 解决方案 1:需要安装第三方插件,这可能并不总是可行的。
  • 解决方案 2:不需要安装任何第三方插件,而是使用 macOS 内置的工具/功能作为标准配置。

解决方案 1:

如果您有幸能够在您的用户系统上安装第三方插件,那么您可以安装 JSON Helper for AppleScript (正如 cmets 中的 @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 的变量。


解决方案 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 文件名包含空格,您需要使用 \\ 对其进行转义。比如~/Desktop/foo\\ bar.json

说明:

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

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

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

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

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

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

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

      s 命令的语法是's/regexp/replacement/flags'

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

      • s/^ *\\[ *\"// 从字符串的开头。

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

      • s/\" *, *\"/,/g 将单个逗号(前面可能有零个或多个空格,和/或后跟零个或多个空格)替换为单个逗号。

    • 第 3 行 上的初始部分: set myList to text items of ... 利用text items 将字符串读入AppleScript list,使用逗号作为分隔符来确定list 的每一项。生成的 Array 被分配给名为 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 数组值中的 JSON escaped special characters。但是,解决方案 1 会解释它们。

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

【讨论】:

  • 我知道在您的示例中文件名是 foobar.json 但是,如果您要使用 变量,例如srcFilePath ,它包含一个 POSIX path 用于与 do shell script command 一起使用,那么无论如何我都会将它放在 single-quotes 中。假设文件名是foo bar.json,那么按照目前的编码,它会因为未转义的空格或没有被引用而失败。请改用以下内容:set srcFilePath to quoted form of (POSIX path of (path to home folder) &amp; "Desktop/foo bar.json") 然后它可以在路径文件名中不带或不带空格的情况下工作。
  • 关于 newline-space 替换的好想法。
  • 对于标准 AppleScript,无论大小写如何,在“...到一个新的 AppleScript 数组。生成的 AppleScript 数组...”中使用“数组”这个词有点误导,因为标准 AppleScript没有array object 但是,它确实有一个list object
【解决方案2】:

如何从如下所示的 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"]

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

检查 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

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

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

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

更通用的解决方案

我决定在 AppleScript 中包含一种更高级的处理 JSON 的方法,部分原因是我最近一直在进行大量的 JSON 处理,而这对我的事件视界来说是全新的;还要证明,使用 AppleScriptObjC,解析甚至非常复杂的 JSON 数据不仅是可能的,而且非常简单。

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

该脚本包含三个部分:它首先导入相关的 Objective-C 框架,该框架赋予 AppleScript 额外的功能;然后,我定义了实际的处理程序本身,称为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 数组。

在这些情况下,它返回的是本机 AppleScript record 对象,所有 JSON 变量都作为属性值存储在记录中。访问变量就变得非常简单了。

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

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

【讨论】:

  • 为什么我不能用dataWithContentsOfURL 替换dataWithContentsOfFile?我必须做些什么才能使这项工作(所以我不必编写临时文件)?
  • @hepcat72 您可以使用dataWithContentsOfURL:dataWithContentsOfURL:options:error:。但是,文件 URL 和文件路径是不同的数据类型,所以我怀疑您将字符串文件路径传递给 JSONtoRecord 处理程序,您需要在其中传递 POSIX filealias«class furl»目的。我将对处理程序进行编辑,使其能够应对任何这些可能性,因此您不必担心。我回家后会做的。
  • 我实际上正在尝试从(本地网络)Web URL(来自我的 HDHomeRun 的频道阵容)检索 JSON,以便我可以处理它并让用户选择一个频道。所以我的评论不准确。我不仅要替换该方法 - 我还想将一个以 https:// 开头的网址传递给它。我尝试了“as url”,也尝试了未成功声明 nsurl。
  • dataWithContentsOfURL 可以在网址上工作吗?还是只是为了文件?
  • @hepcat72 抱歉,我并没有忘记这件事,但是我的笔记本电脑坏了,互联网中断了好几天,我的日常工作让我一直在操蛋。 dataWithContentsOfURL: 实际上可以用于几乎任何性质的远程 URL,只要通过网络传输的数据量相对较小(对于大数据传输有更合适、更快的方法)。您必须通过 NSURL's URLWithString:"https://example.com:448/foo?a=3&amp;b=..." 来构造 NSURL。
猜你喜欢
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-26
  • 2013-09-25
相关资源
最近更新 更多