# The formats in between: why every interchange bug is the same bug

> JSON, YAML, XML, timestamps, text encodings, base64, URLs, diffs. They look like separate topics with separate reference pages. They are one topic: each is a convention for putting meaning into a string so that something else can take it out again, and almost every defect in the set is the two ends disagreeing about what came out.

Source: https://ronutz.com/en/learn/the-formats-in-between  
Updated: 2026-09-09

---

Two notations that belong in the same family: **[cron, the schedule language](https://ronutz.com/en/learn/cron-the-schedule-language)** - five columns of numbers and stars that every Unix box interprets - and **[the Greek alphabet](https://ronutz.com/en/learn/greek-alphabet-the-engineers-second-alphabet)**, which engineering borrows for symbols and then argues about how to pronounce.

## One topic, not eight

A practitioner meets these as separate chores. Somebody hands you a configuration file and it is YAML. A log line has a timestamp in a shape you have not seen. An API returns base64 and you need the bytes back. A merge conflict needs reading. Each gets looked up when it appears and forgotten afterwards, which is why they never accumulate into competence.

They are all the same thing. **Each is a convention for putting meaning into a sequence of characters so that something else can take the meaning out again**, and the interesting failures in every one of them are not parse errors. They are the two ends disagreeing about what came out - which is precisely the failure that lost [Mars Climate Orbiter](https://ronutz.com/en/learn/mars-climate-orbiter-and-the-boundary), where the same bare number meant two different physical quantities on opposite sides of a boundary and both programs were internally correct.

Sorted that way, the reference articles stop being chores and start being a single skill.

## Structure: what counts as a value

**[JSON grammar](https://ronutz.com/en/learn/json-grammar)** is the shortest specification worth knowing by heart, and the reason to know it is what it does *not* say. The interesting cases are all in the gaps: **[duplicate keys](https://ronutz.com/en/learn/json-duplicate-keys)**, where the standard does not say which wins and parsers therefore disagree; **[comments and trailing commas](https://ronutz.com/en/learn/json-comments-and-trailing-commas)**, which are not in the grammar and which half the tooling accepts anyway; and **[string escapes](https://ronutz.com/en/learn/json-string-escapes)**, where the encoding of the text inside the text is its own problem.

Two parsers accepting the same document and producing different objects is a security property, not a curiosity. It is how a filter and the thing behind the filter come to disagree.

**[YAML](https://ronutz.com/en/learn/json-vs-yaml)** buys readability with a much larger surface. **[Anchors and aliases](https://ronutz.com/en/learn/yaml-anchors-and-aliases)** let a document refer to its own parts, which is convenient and is also expansion - the same shape as **[billion laughs](https://ronutz.com/en/learn/billion-laughs-and-entity-expansion)** in XML, where a small document becomes an enormous one on the way in. **[Block scalars](https://ronutz.com/en/learn/yaml-block-scalars)** are where whitespace becomes semantic, and where a certificate pasted into a manifest either survives or does not.

**XML** is the older and more explicit family: **[reading the structure](https://ronutz.com/en/learn/reading-xml-structure)**, **[namespaces](https://ronutz.com/en/learn/xml-namespaces-explained)** which exist so two vocabularies can share a document without colliding, and **[CDATA, comments and processing instructions](https://ronutz.com/en/learn/cdata-comments-and-processing-instructions)** - the parts that are in the file and are not the data.

**[Config formats in practice](https://ronutz.com/en/learn/config-formats-in-practice)** is the comparison across all three, for the moment somebody asks which to use.

## Characters: what the bytes were

Below every format above sits a more basic agreement. **[Character encoding](https://ronutz.com/en/learn/character-encoding)** is the question of which bytes mean which characters, and **[text encodings compared](https://ronutz.com/en/learn/text-encodings-compared)** is the practical version of the same question.

This layer is invisible until it is not, and when it fails it fails in a distinctive way: nothing errors, and the text is simply wrong - a name in a certificate, an accented city in a log, a hostname that does not match. The [Mars](https://ronutz.com/en/learn/mars-climate-orbiter-and-the-boundary) lesson applies verbatim, because both sides were internally correct there too.

**[Base64](https://ronutz.com/en/learn/base64-in-practice)** and **[base32](https://ronutz.com/en/learn/base32)** are the adjacent skill: not encryption, not compression, but a way of moving arbitrary bytes through a channel that only tolerates text. Recognising them on sight, and knowing that recognising them is not the same as reading them, saves a great deal of time in a capture or a log.

## Time: the number that means several things

Timestamps deserve their own group because they are the most common interchange failure in operations and the one people are most confident about.

**[Unix time explained](https://ronutz.com/en/learn/unix-time-explained)** is the base convention. **[Unix time and leap seconds](https://ronutz.com/en/learn/unix-time-and-leap-seconds)** is where it stops being a true count of elapsed seconds, and where the 2012 kernel bug took down major sites over a value that was correct in every individual system and wrong between them. **[Epoch units](https://ronutz.com/en/learn/epoch-units-seconds-to-nanoseconds)** is the seconds-versus-milliseconds-versus-nanoseconds question that produces timestamps in 1970 or in the year 56000. **[ISO 8601 and RFC 3339](https://ronutz.com/en/learn/iso-8601-and-rfc-3339)** is which written form, and which profile of it. And **[time arithmetic and time zones](https://ronutz.com/en/learn/time-arithmetic-and-time-zones)** is the part nobody gets right first time.

If an incident timeline from three systems does not line up, the fault is almost always in this group rather than in anyone's memory of events.

## Identifiers: what the string points at

**[URI, URL and URN](https://ronutz.com/en/learn/uri-url-urn-whats-the-difference)** distinguishes naming from locating, which sounds academic until it decides whether a thing can be fetched. Its security consequence has its own article: **[deceptive URLs](https://ronutz.com/en/learn/deceptive-urls)**, where the string a human reads and the destination a parser derives are not the same - the interchange failure with an adversary attached.

## Change: what is different

**[Reading a diff](https://ronutz.com/en/learn/reading-a-diff)** is the format an engineer sees more often than any other and is taught least often. **[Minimal edits](https://ronutz.com/en/learn/diff-minimal-edits)** explains why a diff sometimes attributes a change to a line nobody touched; **[word and character level](https://ronutz.com/en/learn/diff-word-and-character-level)** is how to see through that; and **[three-way diffs and merge conflicts](https://ronutz.com/en/learn/diff-three-way-and-merge-conflicts)** is the version that appears when two people changed the same thing.

A diff is an interchange format like the rest: a claim about the difference between two states, encoded so a person or a tool can reconstruct it.

## Why this set is a security topic

Every article above describes a place where two implementations can disagree about the meaning of the same bytes, and the [interpreter problem](https://ronutz.com/en/learn/the-interpreter-problem) is what that disagreement becomes when one end is an attacker: a component receives a string, interprets it exactly as documented, and the interpretation is code execution.

The transferable questions are short, and they are the same for all of them:

- **What did the sender mean, and is that written down anywhere?** [Mars Climate Orbiter](https://ronutz.com/en/learn/mars-climate-orbiter-and-the-boundary) had it written down and lost anyway, because nothing compared the document with the traffic.
- **Would a second implementation agree?** Duplicate keys, timestamp precision, whitespace in a block scalar, a normalised URL - if two parsers can differ, a filter and its target can differ.
- **What expands?** Anchors, entities, includes, escapes. Anything that makes a document larger on the way in is a resource question before it is a correctness question.
- **And what is in the file that is not the data?** Comments, processing instructions, byte-order marks, trailing whitespace. Each has been the whole of somebody's outage.
