Я работаю над обработкой метаданных моих ссылок на документы Indesign, используя ExtentdScript.
Я хочу преобразовать объект в строку с помощью JSON.stringify, но когда я его использую, я получаю сообщение об ошибке:
can't execute script in target engine.
Если я уберу linkObjStr = JSON.stringify(linksInfObj); из приведенного ниже кода, все будет работать нормально.
Что эквивалентно JSON.stringify в ExtendScript, или есть ли другие возможности отображать linksInfObj с его правильным содержимым вместо [object object]?
for (var i = 0, len = doc.links.length; i < len; i++) {
var linkFilepath = File(doc.links[i].filePath).fsName;
var linkFileName = doc.links[i].name;
var xmpFile = new XMPFile(linkFilepath, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_READ);
var allXMP = xmpFile.getXMP();
// Retrieve values from external links XMP.
var documentID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
var instanceID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'InstanceID', XMPConst.STRING);
linksInfObj[linkFileName] = {'docId': documentID, 'insId': instanceID};
linkObjStr = JSON.stringify(linksInfObj);
alert('Object' + linksInfObj, true); // I am getting [Object Object] here
alert('String' + linkObjStr, true);
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


ExtendScript не включает объект JSON с соответствующими методами для разбора, а именно JSON.parse() и JSON.stringify(). Он также не предоставляет каких-либо других встроенных функций для анализа JSON.
Рассмотрите возможность использования полифилл для предоставления функций JSON, таких как JSON-js, созданный Дугласом Крокфордом.
Что вам нужно сделать:
Загрузите файл JavaScript с именем json2.js из репозитория Github и сохраните его в том же месте/папке, что и ваш файл .jsx.
Примечание Вы можете просто скопировать и вставить необработанная версия json2.js из того же репозитория Github, чтобы создать файл json2.js вручную, если хотите.
Затем в верхней части вашего текущего файла .jsx вам нужно будет #include файл json2.js, добавив следующую строку кода:
#include "json2.js";
Это аналогично тому, как вы можете использовать оператор import для включения модуля в современный JavaScript (ES6).
путь для местоположения json2.js может быть предоставлен, если вы решите сохранить файл в другом месте/папке, чем ваш файл .jsx.
Включив json2.js в свой файл .jsx, вы получите работающие методы JSON; JSON.parse() и JSON.stringify().
Следующий ExtendScript (.jsx) — это рабочий пример, который генерирует JSON для указания всех ссылок, связанных с текущим документом InDesign (.indd).
пример.jsx
#include "json2.js";
$.level=0;
var doc = app.activeDocument;
/**
* Loads the AdobeXMPScript library.
* @returns {Boolean} True if the library loaded successfully, otherwise false.
*/
function loadXMPLibrary() {
if (!ExternalObject.AdobeXMPScript) {
try {
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
} catch (e) {
alert('Failed loading AdobeXMPScript library\n' + e.message, 'Error', true);
return false;
}
}
return true;
}
/**
* Obtains the values f XMP properties for `DocumentID` and `instanceID` in
* each linked file associated with an InDesign document (.indd). A returns the
* information formatted as JSON,
* @param {Object} doc - A reference to the .indd to check.
* @returns {String} - The information formatted as JSON.
*/
function getLinksInfoAsJson(doc) {
var linksInfObj = {};
linksInfObj['indd-name'] = doc.name;
linksInfObj.location = doc.filePath.fsName;
linksInfObj.links = [];
for (var i = 0, len = doc.links.length; i < len; i++) {
var linkFilepath = File(doc.links[i].filePath).fsName;
var linkFileName = doc.links[i].name;
var xmpFile = new XMPFile(linkFilepath, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_READ);
var allXMP = xmpFile.getXMP();
// Retrieve values from external links XMP.
var documentID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
var instanceID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'InstanceID', XMPConst.STRING);
// Ensure we produce valid JSON...
// - When `instanceID` or `documentID` values equal `undefined` change to `null`.
// - When `instanceID` or `documentID` exist ensure it's a String.
instanceID = instanceID ? String(instanceID) : null;
documentID = documentID ? String(documentID) : null;
linksInfObj.links.push({
'name': linkFileName,
'path': linkFilepath,
'docId': documentID,
'insId': instanceID
});
}
return JSON.stringify(linksInfObj, null, 2);
}
if (loadXMPLibrary()) {
var linksJson = getLinksInfoAsJson(doc);
$.writeln(linksJson);
}
Выход:
Запуск приведенного выше скрипта запишет в консоль JSON в формате, похожем на следующий пример:
{
"indd-name": "foobar.indd",
"location": "/path/to/the/document",
"links":[
{
"name": "one.psd",
"path": "/path/to/the/document/links/one.psd",
"docId": "5E3AE91C0E2AD0A57A0318E078A125D6",
"insId": "xmp.iid:0480117407206811AFFD9EEDCD311C32"
},
{
"name": "two.jpg",
"path": "/path/to/the/document/links/two.jpg",
"docId": "EDC4CCF902ED087F654B6AB54C57A833",
"insId": "xmp.iid:FE7F117407206811A61394AAF02B0DD6"
},
{
"name": "three.png",
"path": "/path/to/the/document/links/three.png",
"docId": null,
"insId": null
}
]
}
Вы заметили, что выходные данные JSON (выше) структурированы иначе, чем вы пытались структурировать их в данном примере. Основное отличие состоит в том, что вы использовали имена файлов ссылок в качестве имен свойств/ключей, как в следующем примере:
Пример проблемной структуры JSON
{
"one.psd": {
"docId": "5E3AE91C0E2AD0A57A0318E078A125D6",
"insId": "xmp.iid:0480117407206811AFFD9EEDCD311C32"
},
"two.jpg": {
"docId": "EDC4CCF902ED087F654B6AB54C57A833",
"insId": "xmp.iid:FE7F117407206811A61394AAF02B0DD6"
}
...
}
Создание JSON, как в этом примере, не идеально, потому что если бы у вас было две ссылки с одинаковым именем, вы бы когда-либо сообщали только об одной из них. У вас не может быть двух свойств/ключей с одинаковыми именами в объекте.
Редактировать:
В ответ на комментарий ОП:
Hi RobC, other than using
#include 'json2.js', is there any other way to include external js file in the JSX file?
Есть несколько альтернативных способов:
Вы можете использовать $.evalFile(). Например, замените #include "json2.js"; следующими двумя строками:
var json2 = File($.fileName).path + "/" + "json2.js";
$.evalFile(json2);
Примечание: В этом примере предполагается, что json2.js находится в той же папке, что и ваш .jsx
В качестве альтернативы, если вы хотите полностью избежать существования дополнительного файла json2.js. Вы можете добавить IIFE (выражение немедленно вызываемой функции) вверху вашего файла .jsx. Затем скопируйте и вставьте в него содержимое файла json2.js. Например:
(function () {
// <-- Paste the content of `json2.js` here.
})();
Примечание: Если вас беспокоит размер кода, рассмотрите минификация содержимое json2.js, прежде чем вставлять его в IIFE.
FWIW, у json2.js есть некоторые проблемы, связанные с преобразованием ExtendScript и заметным Enumerations. Можно предпочесть собственную реализацию Марка Отре с фреймворком IDExtenso: github.com/indiscripts/IdExtenso
Интересно, но, к сожалению, IDExtenso работает только с ExtendScript ToolKit (ESTK), а не с Visual Studio Code.
JSON-js отлично работает, пока кто-то не попытается использовать его в панели CEP ExtendScript в Visual Studio Code. Тестируя его в автономном .jsx в VSCode, JSON.stringify() и JSON.parse() кодируют и декодируют объекты и массивы объектов. Но отправьте те же самые данные через evalScript(), и все, что вы получите, это «ошибка EvalScript», если вам повезет. Это действительно очень плохо, но я вернулся к join() и split().
Кроме того, оператор включения для файла .jsx в VSCode: //@include "./JSON-js/json2.js"
Как вы понимаете, EvalScript, вероятно, не будет работать, потому что любой тип включения зависит от фактического местоположения файла, а скрипт внутри EvalScript не имеет физического местоположения. У меня была аналогичная проблема при использовании evalJSXFile, и, очевидно, она не работала, так как ExtendScript не мог получить этот включенный скрипт. Вы можете обойти это, встроив весь json2.js в свой сценарий, если вам нужно использовать JSON в своем сценарии.
Я применяю Минификатор JavaScript к JSON-js
затем поместите результат в мой скрипт.
Если вы используете отладчик vscode, по моему опыту, эта ошибка означает либо синтаксическую ошибку, либо не находит включаемый файл.