Object Literals

var person = {
    firstName: "Jane",
    lastName:  "Smith",
    email:     "jane@example.com",
    active:    true,
    score:     95.5
};
Show test script
<script runat="server">
/*
 * Chapter: Object Literals
 * Proves:
 *   1. create/access.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var person = { city: "Berlin" }; assert("city", person.city, "Berlin");
</script>

Property Access

// Dot notation (preferred when key is a valid identifier)
var first = person.firstName;
person.city = "New York";

// Bracket notation (required for dynamic keys or reserved words)
var field = "email";
var value = person[field];
person["last-login"] = "2026-01-01";

// Checking for property existence
if (person.hasOwnProperty("city")) {
    Write(person.city);
}

if ("email" in person) {
    // in checks prototype chain too — use hasOwnProperty for own properties
}
Show test script
<script runat="server">
/*
 * Chapter: Property Access
 * Proves:
 *   1. dot vs bracket.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var o = { "full-name": "Ada" }; assert("bracket", o["full-name"], "Ada"); o.age = 1; assert("dot set", o.age, 1);
</script>

Nested Objects

var user = {
    profile: {
        name: "Jane Smith",
        address: {
            city: "Chicago",
            state: "IL"
        }
    },
    settings: {
        theme: "dark",
        notifications: true
    }
};

// Safe deep access (no optional chaining ?. in SSJS)
var city = user.profile && user.profile.address && user.profile.address.city;
city = city || "Unknown";
Show test script
<script runat="server">
/*
 * Chapter: Nested Objects
 * Proves:
 *   1. deep path.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var parsed = { subscriber: { key: "abc" } }; assert("nested", parsed.subscriber.key, "abc");
</script>

Object Iteration

var config = { host: "api.example.com", port: 443, secure: true };

// Always use hasOwnProperty in for...in
for (var key in config) {
    if (config.hasOwnProperty(key)) {
        Write(key + ": " + config[key] + "<br>");
    }
}
Show test script
<script runat="server">
/*
 * Chapter: Object Iteration
 * Proves:
 *   1. for-in + hasOwnProperty.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var config = { a: 1, b: 2 }, n = 0;
for (var k in config) { if (config.hasOwnProperty(k)) n++; }
assert("own keys", n, 2);
</script>

Object as a Lookup Map

Use objects as simple hash maps for fast key lookup:

var statusLabels = {
    "A": "Active",
    "I": "Inactive",
    "P": "Pending",
    "U": "Unsubscribed"
};

var code = "A";
var label = statusLabels[code] || "Unknown";
Write(label); // "Active"
Show test script
<script runat="server">
/*
 * Chapter: Lookup Map
 * Proves:
 *   1. map label.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var labels = { active: "Active", inactive: "Inactive" };
assert("label", labels["active"], "Active");
</script>

Arrays of Objects

Common pattern for working with DE row results:

var rows = Platform.Function.LookupRows("MyDE", "Status", "active");

// rows is an array of row objects
for (var i = 0, len = rows.length; i < len; i++) {
    var row = rows[i];
    Write(row["Email"] + " - " + row["Name"] + "<br>");
}

// Build a summary array
var emails = [];
for (var i = 0, len = rows.length; i < len; i++) {
    emails[emails.length] = rows[i]["Email"];
}
Write("Emails: " + emails.join(", "));
Show test script
<script runat="server">
/*
 * Chapter: Arrays of Objects
 * Proves:
 *   1. collect emails.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var rows = [{ Email: "a@x.com" }, { Email: "b@x.com" }], emails = [];
for (var i = 0; i < rows.length; i++) emails.push(rows[i]["Email"]);
assert("join", emails.join(", "), "a@x.com, b@x.com");
</script>

JSON — Serialization and Parsing

SSJS does not have JSON.stringify or JSON.parse. Use the SFMC equivalents:

Stringify (Object → JSON String)

var data = {
    subscriberKey: "abc123",
    email: "jane@example.com",
    score: 95
};

var jsonString = Platform.Function.Stringify(data);
Write(jsonString);
// {"subscriberKey":"abc123","email":"jane@example.com","score":95}

Stringify is a global SSJS function — not JSON.stringify.

ParseJSON (JSON String → Object)

var jsonString = '{"name":"Jane","score":95}';
var obj = Platform.Function.ParseJSON(jsonString + "");
Write(obj.name); // Jane

The + "" coercion is a useful habit, but not for the reason often stated: ParseJSON returns null for null/undefined input rather than erroring (runtime-verified). It throws when handed a non-string object or array, and the coercion turns such a value into a string so the call stays valid. Always test the result for null.

Full Round-Trip Example

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

// Build an object
var payload = {
    action: "update",
    subscriber: {
        key: Platform.Request.GetQueryStringParameter("sk"),
        status: "active"
    }
};

// Serialize to JSON string
var jsonStr = Platform.Function.Stringify(payload);

// Store in DE
Platform.Function.InsertData("AuditLog", "Payload", jsonStr, "Timestamp", Platform.Function.Now());

// Later: retrieve and parse
var storedJson = Platform.Function.Lookup("AuditLog", "Payload", "ID", "1");
var parsed = Platform.Function.ParseJSON(storedJson + "");
Write(parsed.subscriber.key);
</script>

Working with HTTP API Responses

var req = new Script.Util.HttpRequest("https://api.example.com/data");
req.method = "GET";
req.setHeader("Authorization", "Bearer " + accessToken);
var resp = req.send();

// resp.content is a CLR (.NET) object — must use String() to convert
var body = String(resp.content);

// Now parse as JSON
var data = Platform.Function.ParseJSON(body + "");

if (data && data.results) {
    for (var i = 0, len = data.results.length; i < len; i++) {
        Write(data.results[i].name + "<br>");
    }
}

String() is used specifically to convert CLR response objects to JavaScript strings. This is different from Stringify() (which produces JSON).

Show test script
<script runat="server">
/*
 * Chapter: JSON
 * Proves:
 *   1. Stringify/ParseJSON.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var data = { name: "Jane" };
var jsonString = Platform.Function.Stringify(data);
var obj = Platform.Function.ParseJSON(jsonString + "");
assert("name", obj.name, "Jane");
</script>

Copying Objects

SSJS has no Object.assign or spread syntax. Copy objects manually:

// Shallow copy
function shallowCopy(obj) {
    var copy = {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            copy[key] = obj[key];
        }
    }
    return copy;
}

// Merge two objects (second overwrites first)
function merge(target, source) {
    var result = shallowCopy(target);
    for (var key in source) {
        if (source.hasOwnProperty(key)) {
            result[key] = source[key];
        }
    }
    return result;
}
Show test script
<script runat="server">
/*
 * Chapter: Copying Objects
 * Proves:
 *   1. manual shallow copy.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
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");
}
var src = { a: 1, b: 2 }, dst = {};
for (var k in src) { if (src.hasOwnProperty(k)) dst[k] = src[k]; }
dst.a = 9;
assert("src unchanged", src.a, 1);
assert("dst changed", dst.a, 9);
</script>