Skip to main content
January 26, 2026
Question

Inquiry on Native/In-built Support for Converting IDML to JSON

  • January 26, 2026
  • 3 replies
  • 42 views

I would like to check whether Adobe provides any native or in-built solution to convert an IDML (InDesign Markup Language) file into a JSON format.

 

Currently, we are exploring options to process IDML files programmatically and convert the content into a structured JSON representation for downstream processing.

 

Please let us know if there is any official guidance, documentation, or best practice recommended by Adobe for this use case.

3 replies

Community Expert
January 27, 2026

I don’t normally work in this area, but I wanted to share something that might give you a starting point. This was originally built for Illustrator, so some pieces might not directly translate to InDesign, but the overall structure could be useful.

I cobbled this together from a few sources:

  • A JSON polyfill I found on GitHub

  • Some bits of functionality from other scripts I found online

  • A few pieces I added with ChatGPT’s help cos I have no idea what I'm doing here - honesty is the best policy

 

It’s definitely not a finished or “best practice” version, but it does export document structure (artboards > layers > paths) to JSON.

 

Hopefully, this gives you something to work from or adapt for InDesign scripting.

 

The scripting gurus are better versed in this stuff than I am. But every little helps, or maybe in this case it doesn't.

 

/* ============================
   JSON POLYFILL FOR ILLUSTRATOR
   ============================ */

if (typeof JSON !== "object") {
    JSON = {};
}

(function () {
    "use strict";

    function f(n) {
        return n < 10 ? "0" + n : n;
    }

    if (typeof Date.prototype.toJSON !== "function") {
        Date.prototype.toJSON = function () {
            return isFinite(this.valueOf())
                ? this.getUTCFullYear() + "-" +
                  f(this.getUTCMonth() + 1) + "-" +
                  f(this.getUTCDate()) + "T" +
                  f(this.getUTCHours()) + ":" +
                  f(this.getUTCMinutes()) + ":" +
                  f(this.getUTCSeconds()) + "Z"
                : null;
        };
        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function () {
            return this.valueOf();
        };
    }

    var cx,
        escapable = /[\\\"\u0000-\u001f\u007f-\u009f]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            "\b": "\\b",
            "\t": "\\t",
            "\n": "\\n",
            "\f": "\\f",
            "\r": "\\r",
            "\"": "\\\"",
            "\\": "\\\\"
        },
        rep;

    function quote(string) {
        escapable.lastIndex = 0;
        return escapable.test(string)
            ? "\"" + string.replace(escapable, function (a) {
                  var c = meta[a];
                  return typeof c === "string"
                      ? c
                      : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
              }) + "\""
            : "\"" + string + "\"";
    }

    function str(key, holder) {
        var i,
            k,
            v,
            length,
            mind = gap,
            partial,
            value = holder[key];

        if (
            value &&
            typeof value === "object" &&
            typeof value.toJSON === "function"
        ) {
            value = value.toJSON(key);
        }

        if (typeof rep === "function") {
            value = rep.call(holder, key, value);
        }

        switch (typeof value) {
            case "string":
                return quote(value);

            case "number":
                return isFinite(value) ? String(value) : "null";

            case "boolean":
            case "null":
                return String(value);

            case "object":
                if (!value) {
                    return "null";
                }

                gap += indent;
                partial = [];

                if (Object.prototype.toString.apply(value) === "[object Array]") {
                    length = value.length;
                    for (i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || "null";
                    }

                    v =
                        partial.length === 0
                            ? "[]"
                            : gap
                            ? "[\n" +
                              gap +
                              partial.join(",\n" + gap) +
                              "\n" +
                              mind +
                              "]"
                            : "[" + partial.join(",") + "]";
                    gap = mind;
                    return v;
                }

                if (rep && typeof rep === "object") {
                    length = rep.length;
                    for (i = 0; i < length; i += 1) {
                        if (typeof rep[i] === "string") {
                            k = rep[i];
                            v = str(k, value);
                            if (v) {
                                partial.push(quote(k) + ":" + v);
                            }
                        }
                    }
                } else {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = str(k, value);
                            if (typeof v !== "undefined") {
                                partial.push(quote(k) + ":" + v);
                            }
                        }
                    }
                }

                v =
                    partial.length === 0
                        ? "{}"
                        : gap
                        ? "{\n" +
                          gap +
                          partial.join(",\n" + gap) +
                          "\n" +
                          mind +
                          "}"
                        : "{" + partial.join(",") + "}";
                gap = mind;
                return v;
        }
    }

    if (typeof JSON.stringify !== "function") {
        JSON.stringify = function (value, replacer, space) {
            var i;
            gap = "";
            indent = "";

            if (typeof space === "number") {
                for (i = 0; i < space; i += 1) {
                    indent += " ";
                }
            } else if (typeof space === "string") {
                indent = space;
            }

            rep = replacer;

            if (
                replacer &&
                typeof replacer !== "function" &&
                (typeof replacer !== "object" ||
                    typeof replacer.length !== "number")
            ) {
                throw new Error("JSON.stringify");
            }

            return str("", { "": value });
        };
    }
})();

/* ============================
   ILLUSTRATOR EXPORT SCRIPT (GENERIC)
   ============================ */

function exportToJSON() {
    if (app.documents.length === 0) {
        alert("No document open");
        return;
    }

    var doc = app.activeDocument;

    var jsonData = {
        documentName: "document_name",
        artboards: [],
        layers: []
    };

    // Artboards
    for (var i = 0; i < doc.artboards.length; i++) {
        var ab = doc.artboards[i];
        jsonData.artboards.push({
            name: "Artboard " + (i + 1),
            rect: ab.artboardRect
        });
    }

    // Layers
    for (var j = 0; j < doc.layers.length; j++) {
        var layer = doc.layers[j];
        var layerData = {
            name: "Layer " + (j + 1),
            visible: layer.visible,
            locked: layer.locked,
            paths: []
        };

        // Paths
        for (var k = 0; k < layer.pathItems.length; k++) {
            var p = layer.pathItems[k];
            layerData.paths.push({
                name: "Path " + (k + 1),
                closed: p.closed,
                points: p.pathPoints.length
            });
        }

        jsonData.layers.push(layerData);
    }

    var jsonString = JSON.stringify(jsonData, null, 2);

    var file = new File(Folder.desktop + "/illustrator_export.json");
    file.open("w");
    file.write(jsonString);
    file.close();

    alert("Export complete. File saved to Desktop.");
}

exportToJSON();

 

Community Expert
January 27, 2026

Afaik their is no official documentation or sample to convert IDML to JSON. You will have to understand the IDML schema and then write the convertor yourself. As mentioned by @Peter Kahrel, IDML is a bunch of XML files so XML parsing would be your friend.

-Manan

-Manan
Peter Kahrel
Community Expert
Community Expert
January 26, 2026

An IDML file is in fact a zipped collection of XML files. You cannot therefore convert an IDML file to JSON, you'll have to unpack the IDML, then convert each constituent XML file. Whether there's a documented usecase for converting an IDML's XML files to JSON I've no idea.