0

我有一个我试图在 AppleScript 中使用的 JSON 结果,但是因为顶级项目是“未命名的”,我只能通过管道项目引用来访问它们,在这种情况下是一个数字。结果,我无法遍历它,它必须是硬编码的(向下滚动到最后一个代码示例以了解我的意思)

例如,这是我正在查看的 JSON:

{
    "1": {
        "name": "Tri 1"
    },
    "2": {
        "name": "Tri 2"
    },
    "3": {
        "name": "Tri 3"
    },
    "4": {
        "name": "Orb Dave"
    },
    "5": {
        "name": "Orb Fah"
    }
}

在 JSON Helper 的帮助下,我将 JSON 转换为更可用的格式(对于 AppleScript)。

{|3|:{|name|:"Tri 3"}, |1|:{|name|:"Tri 1"}, |4|:{|name|:"Orb Dave"}, |2|:{|name|:"Tri 2"}, |5|:{|name|:"Orb Fah"}}

然后,我可以使用此代码获取相关对象的“灯光”列表:

set lights to (every item in theReturn) as list
repeat with n from 1 to count of lights
    set light to item n of lights
    log n & light
end repeat

由此,我得到:

(*1, Tri 3*)
(*2, Tri 1*)
(*3, Orb Dave*)
(*4, Tri 2*)
(*5, Orb Fah*)

您可能会注意到结果未按所需顺序排列。索引是灯光列表中的索引。它不是出现在对象顶部的数字。如果您查看前两个预先格式化的区域,您会看到项目 1,2 和 3 是 Tri 1、Tri 2 和 Tri 3。Tri 3 先出现、Tri 1 第二和 Orb 是正确的是第三个。

我需要做的是找到一种能够以任何顺序(排序或未排序)遍历 JSON 并能够将“1”与“Tri 1”、“3”与“Tri 3”和“对齐”的方法5" 与 "Orb Fah"。但我找不到任何方式与返回的 JSON 交互,让我引用第三盏灯并返回它的名称。我似乎能够做到的唯一方法是对光索引进行硬编码,例如:

log |name| of |1| of theReturn
log |name| of |2| of theReturn
log |name| of |3| of theReturn
log |name| of |4| of theReturn
log |name| of |5| of theReturn

这给了我正确名称的正确灯光:

(*Tri 1*)
(*Tri 2*)
(*Tri 3*)
(*Orb Dave*)
(*Orb Fah*)

我认为问题的出现是因为灯光 ID 没有描述符或排序。我无法改变,但我需要以编程方式遍历它们。如上所述对它们进行硬编码是不可接受的。

任何帮助,将不胜感激

4

2 回答 2

2

您在这里处理的是记录列表,而不是列表列表。记录是键/值对。它们没有像列表那样的索引。如果您知道钥匙,那就很容易了,因为您只需要您想要的钥匙。你的记录里面有记录,所以你有两层记录。因此,如果你想要 |name| 的值 |3| 对应的记录 记录然后要求它,因为你已经发现......

set jsonRecord to {|3|:{|name|:"Tri 3"}, |1|:{|name|:"Tri 1"}, |4|:{|name|:"Orb Dave"}, |2|:{|name|:"Tri 2"}, |5|:{|name|:"Orb Fah"}}
set record3name to |name| of |3| of jsonRecord

applescript 中记录的缺点是没有找到记录键的命令。其他编程语言为您提供了查找密钥的工具(如objective-c),但applescript 没有。您必须提前了解它们并按照我的说明使用它们。

如果您不提前知道密钥,那么您可以使用 JSON Helper 以不同的形式为您提供结果,或者使用不同的编程语言(python、ruby 等)从记录中提取信息。

您拥有的另一种选择是仅使用 json 文本本身而不使用 JSON Helper。例如,如果您将 json 作为文本,那么您可以使用文本对象的标准 applescript 命令提取信息。您的 json 文本在第 3 行、第 6 行、第 9 行等包含您想要的信息。您可以利用它来发挥自己的优势并做这样的事情......

set jsonText to "{
    \"1\": {
        \"name\": \"Tri 1\"
    },
    \"2\": {
        \"name\": \"Tri 2\"
    },
    \"3\": {
        \"name\": \"Tri 3\"
    },
    \"4\": {
        \"name\": \"Orb Dave\"
    },
    \"5\": {
        \"name\": \"Orb Fah\"
    }
}"

set jsonList to paragraphs of jsonText

set namesList to {}
set AppleScript's text item delimiters to ": \""
repeat with i from 3 to count of jsonList by 3
    set theseItems to text items of (item i of jsonList)
    set end of namesList to text 1 through -2 of (item 2 of theseItems)
end repeat
set AppleScript's text item delimiters to ""

return namesList
于 2013-07-14T20:51:19.070 回答
2

对于每个索引,遍历列表中的所有项目,寻找名称与索引匹配的项目:

tell application "System Events"
    -- Convert the JSON file to a property list using plutil.
    do shell script "plutil -convert xml1 /Users/mxn/Desktop/tri.json -o /Users/mxn/Desktop/tri.plist"
    -- Read in the plist
    set theItems to every property list item of property list file "/Users/mxn/Desktop/tri.plist"
    set theLights to {}
    -- Iterate once per item in the plist.
    repeat with i from 1 to count of theItems
        set theName to i as text
        -- Find the item whose name is the current index.
        repeat with theItem in theItems
            if theItem's name is theName then
                -- We found it, so add it to the results.
                set theValue to theItem's value
                copy {i, theValue's |name|} to the end of theLights
                -- Move on to the next index.
                exit repeat
            end if
        end repeat
    end repeat
    return theLights
end tell

结果:

{{1, "Tri 1"}, {2, "Tri 2"}, {3, "Tri 3"}, {4, "Orb Dave"}, {5, "Orb Fah"}}

理想情况下,我们可以这样说,而不是嵌套循环:

set theName to i as text
set theItem to (the first item in theItems whose name is theName)

但不幸的是,这会产生错误。


此解决方案还演示了 JSON Helper 的替代方案:您可以使用方便的plutil命令行工具将 JSON 文件转换为属性列表,并使用 System Events 对属性列表的内置支持。

于 2016-12-31T09:28:29.347 回答