What is a tolerant-reader client in the context of consuming a JSON HTTP API, and what concrete parsing rules does it follow so that additive server changes do not break it?
answer
- ignore unknown fields, bind only what you use
- unknown enum -> explicit UNKNOWN branch
- no order or field-count assumptions
- strict about fields you DO use
- read-modify-write drops unknown fields = data loss
basics
~20 sA tolerant reader ignores unknown fields, reads only what it needs, does not depend on field order, and handles unknown enum values with a default branch instead of failing. That lets the server add fields and values without redeploying clients.
solid answer
~50 sA **tolerant reader** extracts only the data it actually uses and tolerates everything else. Rules: ignore unknown fields rather than failing deserialization (disable fail-on-unknown-properties; avoid `additionalProperties: false` on responses you consume); never depend on JSON member order; do not treat absent-versus-null as significant unless the contract says so; map unknown enum values to an `UNKNOWN` case with a sane fallback instead of throwing; do not round-trip data you do not understand through a lossy model if you must echo it back. The payoff is that additive evolution actually stays additive: the server adds fields and enum values continuously, and only clients that need them get updated. The limit is that tolerance must not become guessing. Validate the fields you do depend on strictly and fail loudly when a required field is missing or the wrong type — tolerating that just moves the failure somewhere harder to debug.
go deeper
State the rule — ignore what you do not use, do not crash on unknown fields — and give the enum example.
List the concrete parser settings and explain why unknown enum values are the usual breakage point.
Raise the read-modify-write data-loss trap and the strict-where-it-matters boundary, plus staging tests that inject unknown fields.
Treat it as a published platform contract enforced by client SDKs and conformance tests, so additive evolution scales across many consumers.
## The idea "Be conservative in what you send, liberal in what you accept." A tolerant reader is a client written so that the *only* things it can break on are the parts of the payload it genuinely depends on. Everything else — extra fields, new enum members, reordering, new nested objects — passes through without incident. This is what makes an "additive change" additive in practice; without tolerant readers, adding a field is a breaking change. ## Concrete rules **Ignore unknown fields.** Most libraries fail on unknown properties by default or by common configuration. Turn that off for responses (Jackson's `FAIL_ON_UNKNOWN_PROPERTIES=false`, `serde(deny_unknown_fields)` left off, Pydantic's ignore-extra behaviour). If you validate responses against JSON Schema, do not set `additionalProperties: false`. **Bind only what you use.** A DTO with four fields against a forty-field payload is a feature, not laziness: it shrinks the surface on which the server can break you. **Handle unknown enum values.** The most common tolerant-reader failure. A server adds `status: "paused"`; a client whose enum has three constants throws at parse time, or its exhaustive `switch` falls through to a wrong branch. Map unknown strings to an explicit `UNKNOWN` value and decide deliberately: fail this one record, treat it as not-actionable, or surface it to a human. Never make unknown silently mean the safest-sounding known value if that changes money or access. **No structural assumptions.** JSON object member order is not significant; array order is only significant if documented. Do not depend on field count, on a field always being absent, or on a specific serialization of numbers. **Beware lossy round-trips.** If a client GETs a resource, mutates one field and PUTs it back through a model that drops unknown fields, tolerance in reading becomes **data loss in writing** — the classic tolerant-reader trap. Use PATCH with only the fields you own, or preserve the raw document and merge. ## Where tolerance stops Tolerance is about fields you do not use. For fields you do use, be strict: if `amount` is missing or is a string when you expect a number, fail loudly at the boundary with a clear error. Coercing, defaulting to zero, or silently skipping turns a contract violation into a data-corruption bug discovered much later. ## Contract side The pattern only works if the server publishes the promise: "clients MUST ignore unknown fields and unknown enum values; we may add either at any time." Written down, additions are compatible by definition; unwritten, every addition is a negotiation with the loudest consumer. Some teams reinforce this by injecting a random unknown field into responses in staging so intolerant clients fail during testing rather than at the next feature release.
- How does a tolerant reader cause data loss on a read-modify-write cycle?The client GETs a resource into a model that ignores unknown fields, changes one value and PUTs the whole object back. Fields the model never knew about are absent from the PUT body and the server treats them as cleared. Avoid it by sending PATCH with only owned fields, or by keeping the raw document and merging the change into it.
- Should a tolerant reader ignore a missing required field too?No. Tolerance applies to data you do not consume. A missing or wrongly typed field you depend on is a contract violation and should fail fast at the deserialization boundary with a precise error, so the problem is attributed to the API rather than surfacing later as a null-pointer or a zero amount.
saying these in an interview costs you the question
- Equating tolerant reading with skipping validation entirely
- Leaving fail-on-unknown-properties enabled and then calling every server addition a breaking change
- Mapping unknown enum values onto an existing constant such as ACTIVE or FREE
- Assuming tolerance in the client removes the need for the server to document its compatibility policy
- Round-tripping a partially bound object with PUT and wiping unknown fields