An identifier is a value that uniquely distinguishes an AST object so it can be indexed and referenced during persistence operations. Store it directly on each object under the id key, alongside its concept and settings. section 7.2
IDs solve the reference problem in JSON serialization. Replace a JavaScript object reference such as { ref: targetObject } with { refId: targetObject.id }, preventing reference cycles from breaking JSON.stringify. section 7.2 section 7.6
A practical identifier workflow:
- Generate an ID when creating each AST object, rather than assigning it only during serialization. section 7.2
- Use a string containing random characters; uniqueness matters more than the particular value type. section 7.2
- Index objects by ID during deserialization so refId values can resolve back to reference objects. section 7.6
- Keep generated identifiers separate from JavaScript identifiers derived from business names such as “rental period” and rentalPeriod. section 8.4.1
Rental AST
Creating a Rental record type gives it an ID, while nested Data Attribute and Number objects receive their own IDs. A reference from rentalPriceAfterDiscount to rentalPriceBeforeDiscount can therefore serialize as a refId and later resolve to its target. section 7.2 section 7.6
{
id: "<unique-ID>", #1
concept: "<concept>",
settings: {
// ...
}
}
Inspect the compact AST shape showing the id field attached directly to each object. section 7.2
Listing 7.11 Code for a newId function that generates a random ID
const { nanoid } = require("nanoid")
const newId = () => nanoid(10) #1
Inspect the newId function, which generates ten-character random identifiers with nanoid. section 7.2
Listing 7.15 Transforming an AST into a cycle-free “almost-AST”
const serialize = (value) => {
if (isAstObject(value)) {
const serializedAstObject = {
id: value.id,
concept: value.concept,
settings: {}
}
for (const propertyName in value.settings) {
serializedAstObject.settings[propertyName] =
serialize(value.settings[propertyName])
}
return serializedAstObject
}
if (isAstReferenceObject(value)) {
return ({ #1
refId: isAstObject(value.ref) #2
? value.ref.id
: undefined
})
}
if (Array.isArray(value)) {
return value.map(serialize)
}
return value
}
module.exports.serialize = serialize
Inspect the serializer transforming object references into serializable refId values. section 7.2




