CodeRigor

FREE LESSON

Escape data and serialize deterministic reports

Render inert HTML report data with context-appropriate escaping and produce reproducible JSON without mutating inputs.

A report turns records back into text that another program will interpret. That creates a new boundary. A URL containing & or a label containing < is ordinary data in Python. If placed directly into HTML, those characters can instead start a character reference or markup. The correct operation depends on the destination format and insertion context.

One data model, two output boundaries
start / 2
Plain rows flow into independent HTML and JSON serializers. Escaping choices belong to the output context.
One data model, two output boundaries
Plain rows flow into independent HTML and JSON serializers. Escaping choices belong to the output context.

For HTML text, html.escape encodes the characters that could become markup. For a value inside a quoted HTML attribute, keep quote=True so quotes cannot end the value. Always include the attribute’s surrounding quotes as trusted template syntax. Escape the data once when rendering; keep the original strings in the data model. Repeatedly escaping an already serialized string produces double escaping.

Python
from html import escape

value = 'https://example.test/?q="A&B"'
print(escape(value, quote=True))
print(f'<li data-url="{escape(value, quote=True)}">{escape(value)}</li>')

This exercise puts URLs in text and an inert data-url attribute. It does not make them clickable or run a script that navigates to that attribute. HTML escaping would not make a javascript: href acceptable: scheme and destination policy must be considered before creating active links. Nor does this technique make a safe JavaScript expression, CSS value or arbitrary HTML fragment. Choose a serializer or safe API for each actual context.

The report accepts inventory rows with url and nonnegative integer count. These are already valid data records; rendering does not fetch or reclassify them. Sort a new sequence by the original URL string so the same records have the same order regardless of earlier dictionary insertion order. Keep the original list and row dictionaries unchanged. Stable output makes diffs and fixture tests useful without claiming that byte equality alone proves semantic correctness.

Deterministic output without mutation
start / 2
Create a sorted view, serialize it, and add a single newline; the caller keeps its original order.
Deterministic output without mutation
Create a sorted view, serialize it, and add a single newline; the caller keeps its original order.

JSON has its own serializer. json.dumps handles quotes, backslashes, newlines and Unicode according to JSON syntax. Do not HTML-escape values before encoding JSON: a plain JSON consumer would then receive altered data. Conversely, JSON text is not automatically safe to paste into a browser script element. Our JSON report is a standalone output string, with no script embedding.

Python
import json

rows = [{"url": "https://example.test/é", "count": 2}]
print(json.dumps(rows, ensure_ascii=False, sort_keys=True, separators=(",", ":")))

The build fixes formatting deliberately: compact JSON separators, sorted object keys, Unicode characters retained and exactly one final newline. HTML uses a small list template with one element per line and a final newline. Do not add extra wrapping elements, indentation or a generic pretty-printer if exact output is part of the interface. Empty input is a valid empty report, not an error or missing result.

Implement both renderers and compare their outputs for a quote, ampersand, less-than sign, Unicode character and newline inside a URL string. Those test strings are serialization inputs, not a claim that every string is a valid request URL. Also test count zero, empty rows, a malicious-looking title and reversed input order. Keep content validation, destination policy and output serialization separate so each contract is visible and reviewable.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Watch 13:30–17:15 for list structure and 21:20–23:50 for quoted href attributes. Inspect report insertion points; Python escaping and deterministic serialization are taught in the local lesson.