Как перечислить ключи и значения записи в AppleScript

Когда я использую AppleScript для получения свойств объекта, возвращается запись.

tell application "iPhoto"
    properties of album 1
end tell

==> {id:6.442450942E+9, url:"", name:"Events", class:album, type:smart album, parent:missing value, children:{}}

Как я могу перебирать пары ключ/значение возвращаемой записи, чтобы мне не нужно было точно знать, какие ключи находятся в записи?

Чтобы прояснить вопрос, мне нужно перечислить ключи и значения, потому что я хотел бы написать общую процедуру AppleScript для преобразования записей и списков в JSON, который затем может быть выведен сценарием.


person Bryan Kyle    schedule 05.08.2013    source источник
comment
Если я понимаю вопрос, похоже, что вы хотите сделать: 1) получить список только ключей, 2) принять решение о том, какой ключ вас интересует, и назначить переменную имени этого ключа, затем 3 ) найдите значение, соответствующее этому ключу. Согласно этому, нет простого способа сделать это с помощью applescript, хотя некоторые хаки могут быть возможным   -  person Digital Trauma    schedule 05.08.2013
comment
Записи AppleScript представляют собой фиксированные наборы свойств, в основном аналогичные структурам C, а не произвольные наборы ключей и значений, такие как хэши Perl или словари Python. Поскольку в AppleScript отсутствует самоанализ, нет встроенного способа извлечения списка имен свойств. Существуют различные хаки и кладжи, которые вы можете использовать, но все они неприятны и/или ненадежны. Как уже говорили другие, неясно, почему вы хотите это сделать, а не использовать язык так, как он предназначен для использования.   -  person foo    schedule 06.08.2013
comment
@foo Я думаю, что ваш комментарий, к сожалению, является ответом, который я искал. Однако я не могу принять комментарий в качестве ответа. Не могли бы вы опубликовать комментарий в качестве ответа, чтобы другие могли извлечь выгоду из того, что он является принятым ответом?   -  person Bryan Kyle    schedule 09.08.2013


Ответы (4)


Я знаю, что это старый Q, но теперь есть возможности получить доступ к ключам и значениям (10.9+). В версии 10.9 вам нужно использовать библиотеки сценариев для выполнения этого запуска, в версии 10.10 вы можете использовать код прямо в редакторе сценариев:

use framework "Foundation"
set testRecord to {a:"aaa", b:"bbb", c:"ccc"}

set objCDictionary to current application's NSDictionary's dictionaryWithDictionary:testRecord
set allKeys to objCDictionary's allKeys()

repeat with theKey in allKeys
    log theKey as text
    log (objCDictionary's valueForKey:theKey) as text
end repeat

Это не взлом или обходной путь. Он просто использует «новую» возможность доступа к Objective-C-Objects из AppleScript. Нашла этот вопрос во время поиска по другим темам и не удержалась от ответа ;-)

Обновление для обеспечения функциональности JSON: Конечно, мы можем углубиться в классы Foundation и использовать объект NSJSONSerialization:

use framework "Foundation"
set testRecord to {a:"aaa", b:"bbb", c:"ccc"}

set objCDictionary to current application's NSDictionary's dictionaryWithDictionary:testRecord

set {jsonDictionary, anError} to current application's NSJSONSerialization's dataWithJSONObject:objCDictionary options:(current application's NSJSONWritingPrettyPrinted) |error|:(reference)

if jsonDictionary is missing value then
    log "An error occured: " & anError as text
else
    log (current application's NSString's alloc()'s initWithData:jsonDictionary encoding:(current application's NSUTF8StringEncoding)) as text
end if

Веселись, Майкл / Гамбург

person ShooTerKo    schedule 09.04.2015
comment
Это именно то, о чем я думал. Но вы на самом деле пробовали это с get properties of ..., а не с построенным. - person markhunte; 10.04.2015
comment
Извините за поздний ответ: сам Шейн Стэнли говорит, что мост сценариев не может обрабатывать такие записи. (И если вы понимаете, что происходит за кулисами, у вас может быть некоторое сочувствие к сценарному мосту.) — Я ему верю :-D - person ShooTerKo; 28.04.2016
comment
@ShooTerKo Отличный фрагмент кода. Я реализовал верхний фрагмент для перебора ключей и хотел бы знать, как удалить пару ключ-значение, где theKey as text = "b" (пример). Пробовал objCDictionary's removeObjectForKey:"b" безуспешно. Не могли бы вы помочь, возможно, расширив свой ответ, включив в него эту дополнительную строку? Очень признателен. - person ProGrammer; 08.09.2018
comment
Вы должны создать изменяемый словарь, чтобы использовать removeObjectForKey: set objCDictionary to current application's NSMutableDictionary's dictionaryWithDictionary:testRecord - Ура! - person ShooTerKo; 17.09.2018
comment
Когда я пробую это в записи напоминания, возвращенной из приложения «Напоминания», я получаю ошибку сценария: Can’t make list id "CCB198D9-4122-4161-9FA5-68D61E91919F" of application "Reminders" into the expected type. Любая идея, как решить эту проблему, кроме решения @Chris N (с которым я добился успеха)? - person hepcat72; 06.06.2021

Если вы просто хотите перебрать значения записи, вы можете сделать что-то вроде этого:

tell application "iPhoto"
    repeat with value in (properties of album 1) as list
        log value
    end repeat
end tell

Но мне не очень понятно, чего вы на самом деле хотите добиться.

person Michele Percich    schedule 05.08.2013

По сути, то, что сказали AtomicToothbrush и foo. Записи AppleScript больше похожи на структуры C с известным списком меток, чем на ассоциативный массив с произвольными ключами, и нет (приличного) языкового способа проанализировать метки записи. (И даже если бы они были, у вас все равно возникла бы проблема с их применением для получения значений.)

В большинстве случаев ответ будет «использовать вместо этого библиотеку ассоциативных массивов». Однако вас особенно интересуют метки из значения properties, а это значит, что нам нужен хак. Обычный — вызвать ошибку с помощью записи, а затем проанализировать сообщение об ошибке, что-то вроде этого:

set x to {a:1, b:2}
try
    myRecord as string
on error message e
    -- e will be the string “Can’t make {a:1, b:2} into type string”
end

Разбор этого, и особенно разбор этого с учетом неанглоязычных локалей, остается читателю в качестве упражнения.

person Chris N    schedule 05.08.2013

Ответ ShooTerKo невероятно полезен для меня.

Я подниму еще одну возможность, я удивлен, что я не видел, чтобы кто-то еще упомянул. Мне приходится часто переключаться между AppleScript и JSON в своих сценариях, и если вы можете установить программное обеспечение на компьютеры, на которых должен выполняться сценарий, то я настоятельно рекомендую JSONHelper, чтобы в основном решить всю проблему:

https://github.com/isair/JSONHelper

person Tom Spoon    schedule 09.04.2015
comment
Это приложение действительно классное, и оно также доступно в Mac App Store. Затем он автоматически обновляется ;-) - person ShooTerKo; 10.04.2015
comment
Он говорит мне, что невозможно добавить элемент, потому что он не поддерживает сценарий. когда я пытаюсь добавить это приложение JSONHelper в библиотеку команд applescript. - person luckydonald; 16.02.2021
comment
luckydonald - Не уверен, что вы имеете в виду, пытаясь добавить это приложение JSONHelper в библиотеку команд AppleScript. Вы просто устанавливаете приложение, а затем обращаетесь к нему через Applescript: Чтобы увидеть его команды, откройте его словарь в редакторе сценариев. - person Tom Spoon; 19.02.2021