# FHIR values: false, zero and missing are different facts

Original LockedIn Labs workshop · 45 minutes. Python 3.11+ standard library.
Start with JSON fields and the [reference identity workshop](/training/guides/fhir-references).
The runner reads fourteen authored FHIR R4-shaped Device Observation fixtures.
No patient records, source requests, clinical measurements, database or files are
used. The records use a synthetic vocabulary and a deliberately narrow consumer
contract; this is not a general FHIR or profile validator.

You will preserve value presence, choice type, absence reason, status and unit
identity before handing a source statement to another engineer. A successful
local projection establishes no clinical interpretation, device safety, payment,
source authority or permission.

## 1. Name the value before reading its truth

**FHIR R4** is the pinned 4.0.1 resource format used here. An **Observation** can
represent a measurement or simple assertion about a patient, device or another
supported subject. This exercise uses only invented Device references. A local
code names either a synthetic self-check Boolean or a cycle-duration quantity;
it is not a clinical code set or published implementation guide.

`value[x]` in the specification denotes a choice of a concrete JSON field, such
as `valueBoolean` or `valueQuantity`. It is not a literal JSON property name.
Presence and value are different questions: the key `valueBoolean` can exist
with value `false`; a quantity's numeric value can be zero. Neither is absent.
The [R4 Observation definitions](https://hl7.org/fhir/R4/observation-definitions.html)
describe the value choice and its relationship to the coded question.

A **dataAbsentReason** reports why an expected value is absent. R4's observation
invariant keeps it separate from a present top-level value. A scalar JSON null
is also different from an omitted property; do not replace either with a guessed
number. [FHIR JSON representation](https://hl7.org/fhir/R4/json.html) describes
the general null/omission rules and the separate repeating-primitive exception.
This fixture does not implement primitive extensions or repeating primitives.

**Status** describes the source result's state. The fixture admits only `final`
for its supplied use. A valid preliminary observation can require review under
that application policy. `entered-in-error` is an invalidating status, not a
number to consume just because it is nonzero. A final marker alone establishes
neither clinical correctness nor that a newer source revision does not exist.

## 2. Bind the source question to its expected shape

The source contract requires:

- Literal subject reference `Device/SYNTHETIC-DEVICE-1`.
- One coding with synthetic system, vocabulary version `1` and the expected code.
- Boolean for `self-check-passed`, or exact seconds quantity for `cycle-duration`.
- For quantities, system `http://unitsofmeasure.org`, code `s`, no comparator and
  a nonnegative finite number within this bounded fixture's supported range.

Display labels do not establish code or unit identity. `unit: seconds` cannot
repair `code: min`. The Quantity datatype can express comparisons, such as less
than a value; this exact-value consumer deliberately declines that additional
meaning. These restrictions are an authored contract, not a declaration that
all other FHIR forms are invalid. [R4 Quantity](https://hl7.org/fhir/R4/datatypes.html#Quantity)
is the primary datatype reference.

The six frames explain the runner's separate source records. They are authored
instruction, not live source responses or a browser-based FHIR validator.

## 3. Run fourteen value-presence cases

Download and read [the runner](/templates/fde-fhir-values.py). Keep an untouched
reference and write predictions before viewing the output:

```sh
python3 --version
python3 fde-fhir-values.py > fhir-values-original.json
python3 fde-fhir-values.py --case quantity-value --cycle-value 1 > fhir-values-one.json
```

Each case preserves exact original fixture text in `input_json`, its independent
`contract`, the guarded projection, a deliberately broken truthiness comparison
and a source-immutability check. JSON decimals use Python Decimal when parsed;
the quantity projection's decimal text is explicitly a report field, not a
rewritten FHIR numeric value. No source file is uploaded or fetched.

| Case | Guarded state / reason | Distinction to keep |
| --- | --- | --- |
| `boolean-false` | `supported_value` / `explicit_boolean` | Actual Boolean false remains present |
| `quantity-value` | `supported_value` / `explicit_quantity` | Default numeric zero remains an exact seconds quantity |
| `reported-absence` | `reported_absence` / `not-performed` | An explicit supported source reason, with no value |
| `unexplained-missing` | `no_value_reported` / `absence_reason_not_supplied` | No invented reason or negative result |
| `null-value` | `withheld` / `null_value_property` | A scalar null is not normalized into absence or false |
| `multiple-values` | `withheld` / `multiple_value_choices` | Two top-level value choices cannot become one guessed result |
| `value-and-absence` | `withheld` / `value_and_absence_reason` | False counts as a present value for this check |
| `preliminary` | `withheld` / `status_not_admitted` | Outside this final-only use contract, not generally invalid FHIR |
| `entered-in-error` | `withheld` / `entered_in_error` | Preserve the invalidating marker despite quantity 7 |
| `wrong-choice` | `withheld` / `unexpected_value_choice` | String 0 is not this coded question's quantity |
| `wrong-unit` | `withheld` / `unit_identity_mismatch` | Display seconds does not override coded minutes |
| `quantity-comparator` | `withheld` / `comparator_requires_policy` | Less-than is not an exact point value |
| `wrong-subject` | `withheld` / `subject_mismatch` | A value for another supplied Device cannot answer this question |
| `wrong-code` | `withheld` / `coding_mismatch` | Matching display cannot repair another code |

The broken comparison intentionally uses an `or` expression and a truth test.
It calls false and zero missing, and calls the quantity 7 present even in the
preliminary, entered-in-error or wrong-unit records. Its label is evidence of a
faulty program, not a source assertion or an alternative approved interpretation.

## 4. Read the field path and original record together

Keep this written ledger beside your predictions:

```text
boolean-false:
  present_value_keys: [valueBoolean]
  state: supported_value
  value: {kind: boolean, value: false}
  evidence_path: valueBoolean
  broken shortcut: missing

quantity-value, original:
  present_value_keys: [valueQuantity]
  state: supported_value
  value: {kind: quantity, decimal: "0", code: s}
  evidence_path: valueQuantity.value
  source meta.versionId: r1

reported-absence:
  state: reported_absence
  reason: not-performed
  value: null
  evidence_path: dataAbsentReason.coding[0]

unexplained-missing:
  state: no_value_reported
  reason: absence_reason_not_supplied
  value: null
  evidence_path: null
```

The null in the last two projections is the teaching report's own explicit lack
of a selected result. It is not a null inserted into the original FHIR resource.
The exact source JSON stays unchanged. A report schema and a source resource
schema are different contracts.

Read `interpret`. It matches supplied context, records actual key presence,
checks conflicting shapes and status, then either selects the expected typed
field or preserves an absence/refusal reason. It never derives a result from
display text. `not-performed` is one supported standard absence code; other
reasons remain unsupported here rather than becoming guessed synonyms.

A Boolean false records the source assertion for this particular coded question.
It is not a missing test, a numeric zero or a clinical diagnosis. A numeric zero
retains its quantity type and seconds code; the fixture does not determine
whether a real device could produce that result or what a clinician should do.

## 5. Change zero to one without changing the reading rule

Compare the original quantity case with `fhir-values-one.json`:

```sh
python3 fde-fhir-values.py --case quantity-value --cycle-value 0
python3 fde-fhir-values.py --case quantity-value --cycle-value 1
python3 fde-fhir-values.py --case value-and-absence
```

The guarded projection supports both zero and one. The changed fixture carries
resource version `r2`; keep it separate from the original `r1` record. Those
revision labels are authored fixture context, not observed live server history.
The broken shortcut appears correct for one but still loses zero. Changing test
data to avoid a falsy value does not repair a presence bug.

In value-and-absence, a false Boolean still exists beside dataAbsentReason.
The reader withholds the conflict rather than treating false as if the key were
omitted. Similarly, string `"0"`, Boolean `false` and numeric `0` are different
JSON types. Do not coerce them merely because a user-facing label looks alike.

This source consumer implements one top-level value, no components, panels,
primitive extensions or general profile/terminology validation. It refuses
uninterpreted extension/structure fields conservatively. R4 permits richer
resources; supporting them needs an agreed interpretation policy and tests.
Literal subject matching is not reference resolution or device authentication.
The actual source's profile, timestamps, version selection, access and permitted
use remain receiving-team questions. No source request is made by this program.

## 6. Receive it as a healthcare source-integration pod

Rotate three roles for another run:

- **Builder:** retain exact original JSON, contract, resource/vocabulary versions,
  status, present keys, selected field path and comparison output.
- **Receiver:** change the cycle value without author takeover. Locate both
  explicit values, the reported absence and one withheld conflicting shape.
  Explain which source fact is available and which question remains unresolved.
- **Source/profile and integration owners:** agree real reference resolution,
  coding/unit meaning, supported shapes, permitted status use, freshness and
  access evidence. Keep interpretation authority with the accountable team.

Each participant keeps individual evidence:

```text
Learner / runtime / exact command:
Prediction before execution:
Original input_json / resource id and meta.versionId:
Expected subject / coded question / vocabulary version / value kind:
Observed status / present choice keys / absence reason:
Actual selected value and type / exact evidence path:
My contribution / assistance received:
Changed value / prediction / observed result:
Receiving action actually attempted / assistance:
Unresolved source/profile question / accountable owner / next bounded check:
```

For an authorized receiving experiment, use synthetic records and an agreed
adapter/profile. Ask the next engineer to reproduce a false or zero value and
withhold one unsupported form. Retain the precise remaining source evidence.
A completed local exercise does not approve a clinical workflow or qualify a
person to act independently in one.

## 7. Defend the contract in an interview

**Explain:** How can a false Boolean be present? Locate the actual value key,
its JSON type and the evidence path, then distinguish a source absence reason.

**Debug:** Why can a truthy number still be withheld? Use quantity 7 under a non-admitted status, coded minutes
or a comparator without confusing an application refusal with missing data.

**Design:** Name the source profile, exact coded question, value types, status
policy, unit/comparator rules, current-source selection, reference/access checks
and receiving evidence required before using an Observation in a real workflow.

Primary references checked 28 October 2026:
[HL7 · R4 Observation](https://hl7.org/fhir/R4/observation.html),
[Observation definitions](https://hl7.org/fhir/R4/observation-definitions.html),
[FHIR JSON](https://hl7.org/fhir/R4/json.html),
[Quantity](https://hl7.org/fhir/R4/datatypes.html#Quantity), and
[data absence codes](https://hl7.org/fhir/R4/codesystem-data-absent-reason.html).
The fixtures, conservative consumer, comparisons, visual frames and receiving
exercise are original instruction, not a clinical protocol or full validator.
