frontend
Serialize DOM Tree to JSON in JavaScript
January 24, 2026
Serialize DOM Tree to JSON in JavaScript
Overview
Serializing a DOM tree to JSON means converting the HTML structure into a JSON representation that preserves the element hierarchy, attributes, and text content. This is useful for storing DOM structures, sending them over networks, or manipulating them as data.
Basic Implementation
// Convert HTML DOM tree nodes into JSON format
function serializeDOMTree(node) {
/** Create the json structure for the json data */
let nodeData = {
tag: node.tagName.toLowerCase(),
attributes: {},
children: [],
};
/** Store all the attributes of the element (e.g. class, id, data-cy etc) */
for (let i = 0; i < node.attributes.length; i++) {
const attr = node.attributes[i];
nodeData.attributes[attr.name] = attr.value;
}
/** Loop through the child nodes */
for (let i = 0; i < node.childNodes.length; i++) {
const childNode = node.childNodes[i];
/** If element node found then make recursive call for further children */
if (childNode.nodeType === Node.ELEMENT_NODE) {
nodeData.children.push(serializeDOMTree(childNode));
} else if (childNode.nodeType === Node.TEXT_NODE) {
/** If text node then store the value as child */
const text = childNode.textContent.trim();
if (text) {
nodeData.children.push(text);
}
}
}
return nodeData;
}
console.log(serializeDOMTree(document.body));
Enhanced Implementation
With Options
function serializeDOMTree(node, options = {}) {
const {
includeTextNodes = true,
includeComments = false,
includeWhitespace = false,
attributeFilter = null
} = options;
const nodeData = {
tag: node.tagName ? node.tagName.toLowerCase() : null,
attributes: {},
children: []
};
// Handle attributes
if (node.attributes) {
for (let attr of node.attributes) {
if (!attributeFilter || attributeFilter.includes(attr.name)) {
nodeData.attributes[attr.name] = attr.value;
}
}
}
// Handle children
for (let child of node.childNodes) {
if (child.nodeType === Node.ELEMENT_NODE) {
nodeData.children.push(serializeDOMTree(child, options));
} else if (child.nodeType === Node.TEXT_NODE) {
const text = includeWhitespace ? child.textContent : child.textContent.trim();
if (text && includeTextNodes) {
nodeData.children.push(text);
}
} else if (child.nodeType === Node.COMMENT_NODE && includeComments) {
nodeData.children.push({
type: 'comment',
text: child.textContent
});
}
}
return nodeData;
}
Use Cases
1. DOM Snapshot
const snapshot = serializeDOMTree(document.body);
localStorage.setItem('domSnapshot', JSON.stringify(snapshot));
2. Server Communication
const domJSON = serializeDOMTree(formElement);
fetch('/api/save-form', {
method: 'POST',
body: JSON.stringify(domJSON)
});
3. DOM Comparison
const before = serializeDOMTree(element);
// Make changes
const after = serializeDOMTree(element);
// Compare structures
Best Practices
- Handle Edge Cases: Text nodes, comments, empty elements
- Filter Attributes: Only include needed attributes
- Preserve Structure: Maintain hierarchy accurately
- Performance: Consider for small DOM trees
- Validation: Validate JSON structure