The native JSON object is not available in SFMC SSJS — JSON.parse and JSON.stringify both throw. Use the SFMC-proprietary Platform.Function.ParseJSON and Platform.Function.Stringify (or the Stringify global) instead.

Status legend

Icon Meaning
✅ Works Available and behaves as expected
⚠️ Partial Available but with a documented caveat or bug
❌ Missing Not available — use the workaround

Members

Member ES Status Notes
JSON.parse(text) ES5 ❌ Missing Use Platform.Function.ParseJSON
JSON.stringify(value) ES5 ❌ Missing Use Platform.Function.Stringify or the bare-name Stringify Core global

parse

(ES5) — ❌ Missing. JSON.parse is not available. Use Platform.Function.ParseJSON(string), which parses a JSON string into an SSJS object. Coerce the input to a string first (str + "") to avoid CLR/JS boundary issues.

// ❌ Not available in SFMC:
// var obj = JSON.parse(jsonString);

// ✅ Use Platform.Function.ParseJSON:
var jsonString = '{"name":"Jane","age":30}';
var obj = Platform.Function.ParseJSON(jsonString + "");
Write(obj.name);   // "Jane"

See Platform.Function.ParseJSON for full details.

Show test script
<script runat="server">
Platform.Load("core", "1.1.5");

/*
 * Chapter: parse — JSON.parse is missing; use Platform.Function.ParseJSON
 *
 * Proves:
 *   1. DEVIATION marked "DEV": the native JSON object is MISSING.
 *      typeof JSON is "undefined" (spec/ES5: "object"), and JSON.parse
 *      throws "Object expected: parse" when invoked.
 *      NOTE: merely READING JSON.parse does not throw — Jint resolves the
 *      whole member path to undefined; only the CALL throws.
 *   2. The documented workaround works: Platform.Function.ParseJSON(str + "")
 *      parses a JSON string into an SSJS object, and obj.name is "Jane".
 *   3. Round-trips with deterministic fixtures: nested objects, arrays,
 *      null, booleans, numbers, escaped quotes and non-ASCII characters all
 *      survive Stringify -> ParseJSON unchanged.
 *   4. Documented edge cases of ParseJSON: a top-level JSON array yields an
 *      indexable array; a SCALAR JSON value comes back as a STRING, not a
 *      number/boolean/null; and invalid, empty, null or undefined input
 *      returns null WITHOUT throwing.
 *
 * EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
 * longer matches the documented claim and the page must be revised.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
    var threw = false, msg = "";
    try { fn(); } catch (ex) { threw = true; msg = ex.message; }
    Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}

/* 1. DEVIATION — the native JSON object does not exist. */
try {
    assert("DEV typeof JSON is undefined (spec: object)", String(typeof JSON), "undefined");
} catch (e1) { Platform.Response.Write("FAIL typeof JSON -> THREW: " + e1.message + "\n"); }
try {
    assert("DEV reading JSON.parse yields undefined (spec: function)", String(typeof JSON.parse), "undefined");
} catch (e2) { Platform.Response.Write("FAIL read JSON.parse -> THREW: " + e2.message + "\n"); }
assertThrows("DEV JSON.parse('{\"a\":1}') throws (spec: returns an object)", function () { return JSON.parse('{"a":1}'); });

/* 2. Workaround from the page: Platform.Function.ParseJSON with a coerced string. */
try {
    var jsonString = '{"name":"Jane","age":30}';
    var obj = Platform.Function.ParseJSON(jsonString + "");
    assert("ParseJSON result is an object", String(typeof obj), "object");
    assert("ParseJSON(...).name is 'Jane'", String(obj.name), "Jane");
    assert("ParseJSON(...).age is 30", String(obj.age), "30");
} catch (e3) { Platform.Response.Write("FAIL ParseJSON basic -> THREW: " + e3.message + "\n"); }

/* 3. Round-trip with a deterministic mixed fixture. */
try {
    var fixture = { n: 1.5, s: "x\"y", b: true, z: null, arr: [10, 20, 30], nested: { deep: "ok" }, uni: "caf\u00e9" };
    var round = Platform.Function.ParseJSON(Platform.Function.Stringify(fixture) + "");
    assert("round-trip number survives", String(round.n), "1.5");
    assert("round-trip escaped quote survives", String(round.s), 'x"y');
    assert("round-trip boolean survives", String(round.b), "true");
    assert("round-trip null survives", String(round.z), "null");
    assert("round-trip array element survives", String(round.arr[2]), "30");
    assert("round-trip nested object survives", String(round.nested.deep), "ok");
    assert("round-trip non-ASCII character survives", String(round.uni), "caf\u00e9");
    assert("round-trip non-ASCII length is 4", String(round.uni.length), "4");
} catch (e4) { Platform.Response.Write("FAIL round-trip -> THREW: " + e4.message + "\n"); }

/* 4. Documented ParseJSON edge cases. */
try {
    var list = Platform.Function.ParseJSON('[10,20,30]');
    assert("ParseJSON of a top-level array is indexable", String(list[1]), "20");
} catch (e5) { Platform.Response.Write("FAIL ParseJSON array -> THREW: " + e5.message + "\n"); }
try {
    var scalar = Platform.Function.ParseJSON('42');
    assert("ParseJSON('42') returns a STRING, not a number", String(typeof scalar), "string");
    assert("ParseJSON('42') value is '42'", String(scalar), "42");
} catch (e6) { Platform.Response.Write("FAIL ParseJSON scalar -> THREW: " + e6.message + "\n"); }
try {
    assert("ParseJSON of malformed input returns null (it does NOT throw)", Platform.Function.ParseJSON("{not json") === null, true);
} catch (e7) { Platform.Response.Write("FAIL ParseJSON malformed -> THREW: " + e7.message + "\n"); }
</script>


stringify

(ES5) — ❌ Missing. JSON.stringify is not available. Use Platform.Function.Stringify(value) (no Platform.Load needed) or the Stringify global (requires Platform.Load("Core", "1")).

// ❌ Not available in SFMC:
// var text = JSON.stringify(obj);

// ✅ Use Platform.Function.Stringify:
var obj = { name: "Jane", age: 30 };
var text = Platform.Function.Stringify(obj);
Write(text);   // '{"name":"Jane","age":30}'

// ✅ Or the Stringify global (after Platform.Load):
var text2 = Stringify(obj);

See Platform.Function.Stringify and Stringify for full details.

Show test script
<script runat="server">
Platform.Load("core", "1.1.5");

/*
 * Chapter: stringify — JSON.stringify is missing; use
 * Platform.Function.Stringify or the bare-name Stringify Core global
 *
 * Proves:
 *   1. DEVIATION marked "DEV": the native JSON object is MISSING, so
 *      JSON.stringify throws "Object expected: stringify" when invoked
 *      (spec/ES5: returns a JSON string).
 *   2. The documented workaround works without Platform.Load:
 *      Platform.Function.Stringify({name:"Jane",age:30}) returns exactly
 *      '{"name":"Jane","age":30}' — key order follows insertion order.
 *   3. The bare-name Stringify Core global (available after
 *      Platform.Load("core","1")) produces the identical string.
 *   4. Scalars and structures serialize as documented: strings are quoted,
 *      numbers and booleans are bare, null becomes "null", nested objects
 *      and arrays are emitted inline, and an embedded double quote is
 *      backslash-escaped.
 *   5. DEVIATION marked "DEV": there is no replacer / reviver / space
 *      argument. Platform.Function.Stringify takes exactly ONE argument
 *      (spec: JSON.stringify(value, replacer, space)); a second argument
 *      throws, so pretty-printing and custom replacers are unavailable.
 *   6. DEVIATION marked "DEV": Stringify is a hosted CLR method, so
 *      typeof Platform.Function.Stringify is "clrmethodinfo", not
 *      "function" — the bare-name Core global IS a real "function".
 *
 * EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
 * longer matches the documented claim and the page must be revised.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
    var threw = false, msg = "";
    try { fn(); } catch (ex) { threw = true; msg = ex.message; }
    Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}

/* 1. DEVIATION — no native JSON.stringify. */
try {
    assert("DEV typeof JSON is undefined (spec: object)", String(typeof JSON), "undefined");
} catch (s1) { Platform.Response.Write("FAIL typeof JSON -> THREW: " + s1.message + "\n"); }
try {
    assert("DEV reading JSON.stringify yields undefined (spec: function)", String(typeof JSON.stringify), "undefined");
} catch (s2) { Platform.Response.Write("FAIL read JSON.stringify -> THREW: " + s2.message + "\n"); }
assertThrows("DEV JSON.stringify({a:1}) throws (spec: returns '{\"a\":1}')", function () { return JSON.stringify({ a: 1 }); });

/* 2. Workaround from the page — Platform.Function.Stringify, no Platform.Load needed. */
try {
    var obj = { name: "Jane", age: 30 };
    assert("Platform.Function.Stringify(obj) matches the documented output", String(Platform.Function.Stringify(obj)), '{"name":"Jane","age":30}');
} catch (s3) { Platform.Response.Write("FAIL Platform.Function.Stringify -> THREW: " + s3.message + "\n"); }

/* 3. The bare-name Core global produces the identical string. */
try {
    var obj2 = { name: "Jane", age: 30 };
    assert("Stringify global matches Platform.Function.Stringify", String(Stringify(obj2)), '{"name":"Jane","age":30}');
} catch (s4) { Platform.Response.Write("FAIL Stringify global -> THREW: " + s4.message + "\n"); }

/* 4. Scalars and structures. */
try {
    assert("Stringify('hi') quotes the string", String(Platform.Function.Stringify("hi")), '"hi"');
} catch (s5) { Platform.Response.Write("FAIL Stringify string -> THREW: " + s5.message + "\n"); }
try {
    assert("Stringify(42) emits a bare number", String(Platform.Function.Stringify(42)), "42");
} catch (s6) { Platform.Response.Write("FAIL Stringify number -> THREW: " + s6.message + "\n"); }
try {
    assert("Stringify(true) emits a bare boolean", String(Platform.Function.Stringify(true)), "true");
} catch (s7) { Platform.Response.Write("FAIL Stringify boolean -> THREW: " + s7.message + "\n"); }
try {
    assert("Stringify(null) emits the literal null", String(Platform.Function.Stringify(null)), "null");
} catch (s8) { Platform.Response.Write("FAIL Stringify null -> THREW: " + s8.message + "\n"); }
try {
    assert("Stringify escapes an embedded double quote", String(Platform.Function.Stringify({ s: 'x"y' })), '{"s":"x\\"y"}');
} catch (s9) { Platform.Response.Write("FAIL Stringify escape -> THREW: " + s9.message + "\n"); }
try {
    assert("Stringify of a nested object is inline", String(Platform.Function.Stringify({ a: { b: 1 } })), '{"a":{"b":1}}');
} catch (s10) { Platform.Response.Write("FAIL Stringify nested -> THREW: " + s10.message + "\n"); }

/* 5. DEVIATION — one argument only: no replacer, reviver or space. */
assertThrows("DEV Stringify(value, space) throws — no space arg (spec: pretty-prints)", function () { return Platform.Function.Stringify({ a: 1 }, 2); });
assertThrows("DEV Stringify(value, replacer) throws — no replacer arg (spec: filters keys)", function () { return Platform.Function.Stringify({ a: 1 }, ["a"]); });

/* 6. DEVIATION — hosted CLR method vs. real JS function. */
try {
    assert("DEV typeof Platform.Function.Stringify is clrmethodinfo (spec-style: function)", String(typeof Platform.Function.Stringify), "clrmethodinfo");
} catch (s11) { Platform.Response.Write("FAIL typeof PF.Stringify -> THREW: " + s11.message + "\n"); }
try {
    assert("typeof the bare-name Stringify global is function", String(typeof Stringify), "function");
} catch (s12) { Platform.Response.Write("FAIL typeof Stringify -> THREW: " + s12.message + "\n"); }
</script>

See Also