在AppleScript中引用JSON元素

时间:2013-07-14 13:56:25

标签: json applescript

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

例如,这是我正在看的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没有描述符或排序。我无法改变,但我需要以编程方式迭代它们。如上所述对其进行硬编码是不可接受的。

任何帮助将不胜感激

2 个答案:

答案 0 :(得分: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 Helper的情况下使用json文本。例如,如果您将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

答案 1 :(得分: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文件转换为属性列表,并使用系统事件'内置支持财产清单。