Skip to content
Atlas

Records and formats

Shapes that nest

JSON carries types and nests, which solves the quoting problem and creates the flattening problem. Deciding how a document becomes a row is a design decision, not a mechanical one.

25 minute read


⚡
For the best experience: Download the native Atlas Desktop app for instant test running, native IDE sync, and 100% offline practice.
Download Desktop App→

Flat files treat every column as a scalar, often serialized as text. API payloads frequently deliver structured, hierarchical documents:

{
  "order_id": 1003,
  "customer": {"email": "lin@example.com", "country": "SG"},
  "items": [
    {"sku": "A-1", "quantity": 2},
    {"sku": "B-7", "quantity": 1}
  ],
  "total": 1499.00
}

This format provides two distinct advantages over CSV. Numeric values such as 1499.00 retain native numeric semantics without delimiter ambiguity. Sub-objects such as customer and nested collections such as items maintain explicit boundaries.

Converting hierarchical documents into tabular records requires specific structural decisions.

Flattening is a structural decision

Transforming nested structures into relational rows requires selecting an appropriate representation strategy:

  1. Dotted key flattening: Nested dictionary keys become flat column names, producing columns such as customer.email and customer.country. This strategy handles single nested objects, but fails on array fields like items.
  2. Record explosion: Unnesting arrays into multiple rows emits one record per array element. For order 1003, this produces two rows, one for A-1 and one for B-7. While item details remain distinct, root-level attributes like total are duplicated across rows. An unweighted sum across total yields 2998 instead of 1499.
  3. Serialized storage: Storing the array as raw JSON text within a single column retains root-level cardinality, but obscures nested attributes from relational query engines.

The standard relational pattern splits this data across two related entities: an orders parent table and an order_items child table linked by foreign key. When flattening occurs earlier in a pipeline, data engineers must track aggregation levels to prevent double-counting.

Type preservation and edge cases in JSON

JSON supports strings, numbers, booleans, arrays, objects, and null. While this reduces string-parsing ambiguities, type handling still presents edge cases:

  • Missing keys versus null values: A missing key indicates the attribute was omitted at the source, while an explicit null indicates the value was known to be empty. Flattening transformations often collapse this distinction into a single null representation.
  • Floating-point precision: JSON numbers do not enforce fixed decimal precision. Monetary quantities deserialized into floating-point variables can introduce fractional rounding errors. Financial applications store monetary amounts as string representations of exact decimals or as integers in minor currency units (such as cents).

What the exercise asks

Implement three operations:

  1. Flatten nested dictionaries using dotted key paths.
  2. Explode nested list fields into distinct rows while preserving parent identifiers.
  3. Construct a validation check that identifies inflation when summing parent attributes across exploded rows.

Detecting grain mismatches early prevents silent aggregation bugs in downstream transformations.