Нужно в JSON преобразовать объект в ExtendScript - PullRequest
1 голос
/ 30 мая 2019

Я работаю над обработкой метаданных ссылок на документы 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);

}

1 Ответ

2 голосов
/ 31 мая 2019

ExtendScript не включает объект JSON со связанными методами для синтаксического анализа, а именно JSON.parse() и JSON.stringify(). Он также не предоставляет никакой другой встроенной функции для анализа JSON.


Решение:

Попробуйте использовать polyfill для обеспечения функциональности JSON, например JSON-js , созданный Дугласом Крокфордом.

Что вам нужно сделать:

  1. Загрузите файл JavaScript с именем json2.js из репозитория Github и сохраните его в том же месте / папке, что и ваш файл .jsx.

    Примечание Вы можете просто скопировать и вставить raw версию json2.js из того же репозитория Github, чтобы вручную создать файл json2.js , если вы предпочитают.

  2. Затем в верхней части текущего файла .jsx вам потребуется #include файл json2.js, добавив следующую строку кода:

    #include "json2.js";
    

    Это аналогично тому, как вы можете использовать оператор import для включения модуля в современный JavaScript (ES6).

    A pathname для местоположения json2.js может быть предоставлено, если вы решите сохранить файл в другом месте / папке, чем ваш .jsx файл.

  3. Включив json2.js в ваш файл .jsx, вы получите рабочие методы JSON; JSON.parse() и JSON.stringify().


* * Пример тысяча шестьдесят-два: * * тысяча шестьдесят-три

Следующий ExtendScript (.jsx) является рабочим примером, который генерирует JSON для указания всех ссылок, связанных с текущим документом InDesign (.indd).

example.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
    }
  ]
}

Sidenote: Моделирование вашего JSON:

Вы заметили, что вывод JSON (см. Выше) структурирован иначе, чем вы пытались структурировать его в данном примере. Основное отличие состоит в том, что вы использовали имена ссылок в качестве имен свойств / ключей, например, в следующем примере:

Пример проблемной структуры JSON

{
  "one.psd": {
    "docId": "5E3AE91C0E2AD0A57A0318E078A125D6",
    "insId": "xmp.iid:0480117407206811AFFD9EEDCD311C32"
  },
  "two.jpg": {
    "docId": "EDC4CCF902ED087F654B6AB54C57A833",
    "insId": "xmp.iid:FE7F117407206811A61394AAF02B0DD6"
  }
  ...
}

Создание JSON, подобного этому примеру, не идеально, потому что если бы у вас было две ссылки с одинаковым именем, вы бы сообщали только об одной из них. У вас не может быть двух свойств / ключей с одинаковым именем в объекте.


Edit:

В ответ на комментарий ОП:

Привет, RobC, кроме использования #include 'json2.js', есть ли другой способ включить внешний файл js в файл JSX?

Существует несколько альтернативных способов:

  1. Вы можете использовать $.evalFile(). Например, замените #include "json2.js"; на следующие две строки:

    var json2 = File($.fileName).path + "/" + "json2.js";
    $.evalFile(json2);
    

    Примечание: В этом примере предполагается, что json2.js находится в той же папке, что и ваш .jsx

  2. В качестве альтернативы, если вы хотите полностью избежать существования дополнительного файла json2.js. Вы можете добавить IIFE (выражение для немедленного вызова функции) вверху файла .jsx. Затем скопируйте и вставьте в него содержимое файла json2.js . Например:

    (function () {
        // <-- Paste the content of `json2.js` here.
    })();
    

    Примечание: Если размер кода является проблемой, рассмотрите минимизацию содержимого json2.js перед вставкой его в IIFE.

...