需要 JSON 将 ExtendScript 中的对象字符串化
Need to JSON stringify an object in ExtendScript
我正在使用 ExtentdScript 处理我的 Indesign 文档链接的元数据信息。
我想使用 JSON.stringify
将对象转换为字符串,但是当我使用它时,出现错误提示:
can't execute script in target engine
.
如果我从下面的代码中删除 linkObjStr = JSON.stringify(linksInfObj);
,那么一切正常。
什么与 ExtendScript 中的 JSON.stringify
等价,或者是否有任何其他可能性显示 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);
}
ExtendScript 不包含 JSON 对象和相关的解析方法,即 JSON.parse()
和 JSON.stringify()
。它也不提供任何其他用于解析 JSON.
的内置功能
解决方案:
考虑使用 Douglas Crockford 创建的 polyfill to provide JSON functionality such as JSON-js。
您需要做的事情:
从 Github 存储库下载名为 json2.js 的 JavaScript 文件,并将其保存在与 .jsx
相同的 location/folder 中文件。
注意 您只需从同一个 Github 存储库复制并粘贴 raw version of json2.js 即可创建 json2.js 如果愿意,请手动归档。
然后在当前 .jsx
文件的顶部,您需要通过添加以下代码行 #include
json2.js
文件:
#include "json2.js";
这类似于您在现代 JavaScript (ES6) 中如何使用 import
语句来包含模块。
如果您决定将文件保存在与 .jsx
文件.
通过在 .jsx
文件中包含 json2.js
,您现在可以使用 JSON 方法; JSON.parse()
和 JSON.stringify()
.
示例:
下面的 ExtendScript (.jsx
) 是一个工作示例,它生成 JSON 以指示与当前 InDesign 文档 (.indd
) 关联的所有 link。
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
}
]
}
旁注:为您的 JSON 建模:
您会注意到 JSON 输出(上图)的结构与您在给定示例中尝试构建它的方式不同。主要区别在于您使用 link 文件名作为 property/key 名称,例如以下示例:
有问题的示例 JSON 结构
{
"one.psd": {
"docId": "5E3AE91C0E2AD0A57A0318E078A125D6",
"insId": "xmp.iid:0480117407206811AFFD9EEDCD311C32"
},
"two.jpg": {
"docId": "EDC4CCF902ED087F654B6AB54C57A833",
"insId": "xmp.iid:FE7F117407206811A61394AAF02B0DD6"
}
...
}
像这个例子一样生成 JSON 并不理想,因为如果您有两个 link,并且都具有相同的名称,您将只会报告其中一个。一个对象中不能有两个同名的 properties/keys。
编辑:
作为对 OP 评论的回应:
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 (Immediately Invoked Function Expression) at the top of your .jsx
file. Then copy and paste the content of the json2.js 文件。例如:
(function () {
// <-- Paste the content of `json2.js` here.
})();
注意: 如果代码大小是一个问题,那么在将其粘贴到 IIFE 之前考虑 minifying json2.js
的内容。
我申请了JavaScript Minifier to JSON-js
然后把结果放到我的脚本中。
我正在使用 ExtentdScript 处理我的 Indesign 文档链接的元数据信息。
我想使用 JSON.stringify
将对象转换为字符串,但是当我使用它时,出现错误提示:
can't execute script in target engine
.
如果我从下面的代码中删除 linkObjStr = JSON.stringify(linksInfObj);
,那么一切正常。
什么与 ExtendScript 中的 JSON.stringify
等价,或者是否有任何其他可能性显示 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);
}
ExtendScript 不包含 JSON 对象和相关的解析方法,即 JSON.parse()
和 JSON.stringify()
。它也不提供任何其他用于解析 JSON.
解决方案:
考虑使用 Douglas Crockford 创建的 polyfill to provide JSON functionality such as JSON-js。
您需要做的事情:
从 Github 存储库下载名为 json2.js 的 JavaScript 文件,并将其保存在与
.jsx
相同的 location/folder 中文件。注意 您只需从同一个 Github 存储库复制并粘贴 raw version of json2.js 即可创建 json2.js 如果愿意,请手动归档。
然后在当前
.jsx
文件的顶部,您需要通过添加以下代码行#include
json2.js
文件:#include "json2.js";
这类似于您在现代 JavaScript (ES6) 中如何使用
import
语句来包含模块。如果您决定将文件保存在与
.jsx
文件.通过在
.jsx
文件中包含json2.js
,您现在可以使用 JSON 方法;JSON.parse()
和JSON.stringify()
.
示例:
下面的 ExtendScript (.jsx
) 是一个工作示例,它生成 JSON 以指示与当前 InDesign 文档 (.indd
) 关联的所有 link。
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
}
]
}
旁注:为您的 JSON 建模:
您会注意到 JSON 输出(上图)的结构与您在给定示例中尝试构建它的方式不同。主要区别在于您使用 link 文件名作为 property/key 名称,例如以下示例:
有问题的示例 JSON 结构
{
"one.psd": {
"docId": "5E3AE91C0E2AD0A57A0318E078A125D6",
"insId": "xmp.iid:0480117407206811AFFD9EEDCD311C32"
},
"two.jpg": {
"docId": "EDC4CCF902ED087F654B6AB54C57A833",
"insId": "xmp.iid:FE7F117407206811A61394AAF02B0DD6"
}
...
}
像这个例子一样生成 JSON 并不理想,因为如果您有两个 link,并且都具有相同的名称,您将只会报告其中一个。一个对象中不能有两个同名的 properties/keys。
编辑:
作为对 OP 评论的回应:
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 (Immediately Invoked Function Expression) at the top of your.jsx
file. Then copy and paste the content of the json2.js 文件。例如:(function () { // <-- Paste the content of `json2.js` here. })();
注意: 如果代码大小是一个问题,那么在将其粘贴到 IIFE 之前考虑 minifying
json2.js
的内容。
我申请了JavaScript Minifier to JSON-js
然后把结果放到我的脚本中。