GeneLeaf

Docs › Pedigree JSON

Pedigree JSON, version 0.4

Status: Final. Date: 2026-10-06. Media-type-style name: pedigree-json/0.4. File convention: *.pedigree.json.

Pedigree JSON is an open, plain-JSON format for exchanging a patient family history: everything a pedigree diagram shows (individuals, sex, vital status, dates, coded health conditions, parent/sibling/partner relationships) plus what research and clinical analysis need (coded conditions, stated-versus-inferred relationships, multi-family collections, a de-identification declaration). Think of it as an unformat: it invents almost nothing, and just writes down obvious ideas (name your fields, say what you know, say how sure you are) so that people will actually use them. It is vendor-neutral: nothing in it depends on any one tool, and anyone may read, write, implement, or build on it freely (see §16).

It is meant for the whole community that works with pedigrees: genetic counselors, clinical geneticists, physicians, researchers, and the people who build their software. It aims to sit alongside the formats those groups already use, not to replace them, and §14 says how it maps to FHIR FamilyMemberHistory, GA4GH Phenopackets, and PLINK .PED.

This document is the normative rule set. The companion JSON Schema is pedigree-json-0.4.schema.json. The schema covers structure and types; the rules in §12 are checked in code. The key words MUST, MUST NOT, SHOULD, and MAY in this document are used as in RFC 2119 and RFC 8174 when written in capitals; elsewhere "must", "should", and "may" carry the same force.

Contents

  1. Requirements
  2. Document shape
  3. Layers
  4. Sections
  5. People
  6. Conditions
  7. Relationships and inference levels
  8. The disease index
  9. Forms of a document
  10. Presentation
  11. De-identification
  12. Semantic validation
  13. Reserved
  14. Standards alignment
  15. Changelog
  16. Conformance, versioning, and openness

1. Requirements

  1. Human readable. Plain JSON with spelled-out keys. Anyone can read a document without this spec.
  2. Flexible but unambiguous. Every field is optional, the core vocabulary is closed, and new information is added by adding fields, never by reinterpreting old ones.
  3. Optional multi-family. One family is a document; many are a collection of the same shape, for cross-family analysis.
  4. Shortcuts for analysis. Stated relationships (kin), inferred ones (infer), and a derived disease lookup (index).
  5. Encoded data. Inline base64 is possible but discouraged; link out first.
  6. Common use cases. Symbol positions, annotations, title text, free text.
  7. Color-coded symbols. Quarter-symbol fills driven by a legend.
  8. Link-out by standard URI (public FQDN or filesystem).
  9. LLM and database friendly. A dense compact form for models, a uniform normalized form for JSONB, and a JSON Schema for both.
  10. Not everything now. Anticipated extensions are reserved (§13).

2. Document shape

A document is one JSON object with four sections, each about a different thing:

Key Holds
format Required. "pedigree-json/0.4": what this is and which version
meta The document itself: family id, title and header text, free text, notes, links, the de-identification declaration
pedigree The family: the condition dictionary, people, siblings, couples
view How to draw it (presentation)
index Derived lookup tables (rebuildable)

It is either a pedigree (has pedigree) or a collection (has families), never both. A collection is { format, meta?, families: [ … ], index? } where every family is the same shape as a pedigree document, minus format, and with meta.family required.

{
  "format": "pedigree-json/0.4",
  "meta": {
    "family": "doe",
    "title": "Doe Family",
    "text": "Referred for early-onset colon cancer; father's line uncertain."
  },
  "pedigree": {
    "conditions": {
      "crc":    { "label": "Colon cancer", "codes": ["ICD10:C18.9"] },
      "asthma": { "label": "Asthma",       "codes": ["ICD10:J45"] }
    },
    "people": [
      { "id": 1, "sex": "M", "name": { "given": "Robert", "family": "Doe" },
        "dob": "1955-02-10", "deceased": true },
      { "id": 2, "sex": "F", "name": { "given": "Carol", "family": "Doe" }, "dob": "1957-08-22" },
      { "id": 3, "sex": "M", "name": { "given": "Steven", "family": "Doe" }, "dob": "1982-03-01",
        "proband": true,
        "health": [{ "condition": "crc", "onset": "P38Y", "source": "documented" }, "asthma"],
        "parents": [1, { "id": 2, "type": "step" }],
        "view": { "pos": [120, 240] } },
      { "id": 4, "sex": "F", "name": { "given": "Nancy", "family": "Doe" }, "dob": "1984-11-19",
        "parents": [1, 2] },
      { "id": 9, "sex": "M",
        "health": [{ "condition": "crc", "source": "reported" }],
        "kin": { "of": 3, "rel": "GRFTH" },
        "infer": { "candidates": ["FF", "MF"], "chosen": "FF", "level": 2,
                   "basis": "only the father's line has recorded data" } }
    ],
    "siblings": [[3, 4]],
    "couples": [{ "partners": [1, 2], "consanguineous": true }]
  },
  "view": {
    "show": { "title": true },
    "labels": { "name": true, "dob": true, "health": [true] },
    "legend": { "crc":    { "color": "#d62728", "slot": "NW" },
                "asthma": { "color": "#1f77b4", "slot": "NE" } }
  }
}

2.1 Conventions

3. Layers

The sections are also layers that can be stripped independently. A consumer that wants only the facts reads pedigree (and meta) and ignores the rest.

Layer Where Contents
Facts meta, pedigree Stated and deterministic facts
Inference kin, infer on a person What was said vaguely, and what was concluded from it (§7)
Presentation view (and a person's view) Positions, colors, which labels to draw (§10)
Derived index Rebuildable lookup tables (§8)

The inference levels are defined in §7: the higher the level, the higher the uncertainty.

4. Sections

4.1 meta

Everything about the document rather than the people in it. All keys optional.

Key Type Notes
family string Family id (opaque, no :). Required inside a collection
title, subtitle, footer string Header text drawn above and below the diagram
text string Free-text description of the family. Not the source narrative (see narrative)
notes array Annotations: strings or {text, author?, date?}
as_of date When ages were recorded: a person's age is their age on this date
narrative string or Reference The original free-text narrative this was extracted from: inline text, or a link or encoded payload (§5.1). A plain string is a primary form, not a shorthand, so normalization leaves it alone. Discouraged: it costs space and can carry PHI (§11)
links, attachments array §5.1
identifiers array {system, value} for the family as a whole (e.g. a study id)
deidentified array §11
attestation object §11.4
ext object Extensions

A collection's own meta may hold title, text, notes, links, deidentified, attestation and ext.

4.2 pedigree

Required, but may be empty ("pedigree": {}): a document grows as people are added. The family itself.

Key Type Notes
conditions object The condition dictionary (§6)
people array §5
siblings array Arrays of two or more person ids. One array per sibling group
couples array {partners: [a, b], consanguineous?: bool}. Exactly two partners. A person with several partners has several entries

4.3 view and index

§10 and §8.

5. People

Key Type Notes
id integer Required
sex M F U O Required. Closed set. U = not recorded, O = other/intersex. Mapping to FHIR and .PED in §14
name string or object {given?, middle?, family?, text?}. A plain string is the text form (e.g. a pseudonym "patient_123")
dob date Truncatable
dod date Date of death. Implies deceased: true
deceased boolean true = deceased, date unknown (or known); false = known living; absent = not recorded
age integer Age in years on meta.as_of, for a living person. Use it when dob is not known (a stated age and a dob must agree within a year, V15)
age_at_death integer Age in years at death, for a deceased person (V15)
proband boolean The index case. At most one per family
ancestry object {ashkenazi_jewish?, race_ethnicity?}. race_ethnicity is one of white, black_african_american, hispanic_latina, asian, pacific_islander, native_american_alaska_native, other, unknown: broad categories; map to a model's own when running it
genetics array Genetic test results: {gene, result, variant?, zygosity?, date?}. gene is an HGNC symbol; result is pathogenic, likely_pathogenic, vus or negative (§6.4)
risk_factors object Personal factors that risk models use, normally on the proband (§6.4)
health array §6.2
parents array Up to two. A bare id is a biological parent; {id, type} qualifies it. type: bio (default), adopt, step, foster
kin object How the user described this person (§7)
infer object What was concluded from kin
same_as string Global reference to the same real person in another family
notes, links, attachments, identifiers array As on the pedigree
view object {pos?, fill?} (§10)
ext object Extensions

Siblings and partners are not stored on the person; they live in the pedigree's siblings and couples. Parents are stored on the child, which makes "who are this person's parents" a local read.

One shape serves links, attachments, and narrative:

{ "href": "https://ehr.example.org/family/48213", "title": "EHR record",
  "rel": "related", "mediaType": "text/html", "sha256": "…" }

6. Conditions

6.1 The dictionary

Every condition mentioned on a person is declared once in the family's conditions dictionary. People refer to it by key. There are no free-text condition strings on people.

"conditions": {
  "crc": { "label": "Colon cancer",
           "codes": ["ICD10:C18.9", { "system": "http://snomed.info/sct", "code": "363406005" }] }
}
Prefix System URI
ICD10 http://hl7.org/fhir/sid/icd-10
ICD10CM http://hl7.org/fhir/sid/icd-10-cm
SNOMED http://snomed.info/sct
HPO http://purl.obolibrary.org/obo/hp.owl
OMIM http://www.omim.org
MONDO http://purl.obolibrary.org/obo/mondo.owl

6.2 Health entries

"health": [
  { "condition": "crc", "onset": "P38Y", "status": "affected", "source": "documented",
    "notes": ["Diagnosed at routine screening"] },
  "asthma"
]

6.3 Canonical condition key for cross-family matching

Local keys collide across families ("c1" in one family is not "c1" in the next). Everything that crosses families uses the canonical condition key:

  1. the first entry of codes, as PREFIX:code (using the prefix table where the system is known, otherwise <system>|<code>); else
  2. text: plus the label lowercased with whitespace collapsed.

Coded and uncoded spellings of the same disease therefore do not match each other. That is a deliberate consequence: a writer that wants cross-family analysis should code its conditions. Hierarchical matching (ICD10:C18 covering ICD10:C18.9) is a query-time behavior and is not stored.

6.4 Clinical data for risk models

Pedigree risk models (Gail, Claus, Tyrer-Cuzick, BOADICEA, BRCAPRO, PREMM5, MMRpro) each need a different minimum of data; this format carries the union of what they ask for, all optional. Models use the structures above plus:

7. Relationships and inference levels

Relationships carry an inference level (0 to 3). The level rises with the uncertainty.

Level Name Meaning Stored in
0 known The user said it parents, siblings, couples, kin
1 deterministic Follows logically (children of the same two parents are siblings) Core, optionally (derivable, so writers may omit)
2 probable A choice among possibilities was made on a stated basis infer only
3 possible Several possibilities and none chosen infer only (nothing is materialized)

Level 0 is never altered and never lost. What the user said is kept verbatim in kin, even after it has been resolved to a graph edge.

7.1 kin: what the user said

"kin": { "of": 3, "rel": "GRFTH", "side": "paternal" }

A person with kin need not have any parents: kin alone places them.

7.2 Paths

A path is a string of steps read left to right from of to the person. Empty string = the same person.

Step Move
F to the father
M to the mother
P to a parent, sex not specified
C to a child
S to a sibling

W (partner) is reserved for in-laws. The sex of a final F/M step must agree with the person's sex (rule V9).

A RoleCode expands to one or more candidate paths (a table the spec maintains; GRFTH = FF, MF; PGRFTH = FF; MGRFTH = MF; FTH = F; GRPRN = FP, MP; AUNT = PS with the person's sex deciding). side filters the candidates.

7.3 infer: what was concluded

"infer": { "candidates": ["FF", "MF"], "chosen": "FF", "level": 2,
           "basis": "only the father's line has recorded data" }
Key Notes
candidates Every path consistent with kin (after side)
chosen The path taken, if any. Must be one of candidates
level 1 if exactly one candidate (nothing was a guess), 2 if chosen was picked among several, 3 if none was chosen
basis Free text: why this choice

8. The disease index

An optional derived lookup for fast "who had what, and how are they related".

"index": {
  "of": "sha256:9f2c…",
  "proband": 3,
  "conditions": {
    "ICD10:C18.9": [
      { "id": 3, "path": "",   "level": 0 },
      { "id": 9, "paths": ["FF", "MF"], "chosen": "FF", "level": 2 }
    ],
    "ICD10:J45":   [ { "id": 3, "path": "", "level": 0 } ]
  }
}

9. Forms of a document

9.1 Compact and normalized profiles

Both are valid Pedigree JSON and mean the same thing.

Compact Normalized
Shorthands used wherever lossless none
parents [1, {"id":2,"type":"step"}] [{"id":1},{"id":2,"type":"step"}]
health ["asthma"] [{"condition":"asthma"}]
name may be a string always an object
notes, links strings objects
codes "ICD10:C18.9" {system, code}
Use LLM output, hand authoring, files databases, schema-constrained decoding

A reader accepts both. A writer picks one. Normalization is the canonical ingest step for a database.

9.2 Canonical serialization

Byte-identical output needs one rule set. Because JSONB discards key order and whitespace, key order is not part of the format: canonical bytes are the RFC 8785 (JCS) form, which sorts keys and removes whitespace. Equality of two documents is semantic (parsed value equality).

Within that, array order is fixed:

Pretty-printed JSON is fine for humans and is not canonical.

9.3 Files

10. Presentation: view

Everything about how a pedigree is drawn is in view and can be stripped without losing a fact.

"view": {
  "show":   { "title": true, "subtitle": true, "footer": true },
  "labels": { "name": true, "dob": true, "health": [true, false, false] },
  "legend": { "crc": { "color": "#d62728", "slot": "NW" } }
}
"view": {
  "notes": [ { "headline": "Check", "text": "Dates from Aunt May, not confirmed", "pos": [320, 40], "color": "#d62728", "bold": true } ]
}

11. De-identification

The format's commitment is narrow: make it easy to see, and mechanically check, which fields a writer claims are free of protected health information. It does not verify the claim.

11.1 The deidentified list

meta.deidentified is an array of field paths. An entry asserts that the named field contains no PHI. The field itself stays in place, with its own name, and the document stays valid.

{
  "format": "pedigree-json/0.4",
  "meta": {
    "family": "fam_007",
    "title": "Family 007",
    "deidentified": ["meta.family", "meta.title", "pedigree.people.name",
                     "pedigree.people.dob", "pedigree.people.dod"]
  },
  "pedigree": {
    "people": [
      { "id": 3, "sex": "M", "name": "patient_123", "dob": "1982", "proband": true },
      { "id": 1, "sex": "M", "name": "patient_124", "dob": "1955", "dod": "2011" }
    ]
  }
}

11.2 PHI-capable fields

A closed list. Anything here that is present and not covered by a deidentified list is treated as possibly containing PHI.

Field HIPAA identifier (45 CFR 164.514(b)(2))
pedigree.people.name Name
pedigree.people.dob, .dod Dates (all elements except year)
meta.identifiers, pedigree.people.identifiers MRN, SSN, plan/account/license numbers, device and other ids
meta.links, pedigree.people.links Web URL, and any file path
meta.attachments, pedigree.people.attachments Photographic images, finger/voice prints, any document
meta.family, .title, .subtitle, .footer, .text, .notes, .narrative; pedigree.people.notes, pedigree.people.health.notes Free text: any of the 18
meta.ext, pedigree.people.ext Opaque: may contain anything
contact (reserved) Address, phone, fax, email, IP

Not PHI-capable: sex, proband, health, parents, kin, infer, siblings, couples, view, index, conditions. They are health data and can still re-identify (§11.5), but deidentified does not speak to them.

11.3 What this gives a researcher

Scanning 1000 pedigrees:

  1. Criteria check: does each file list the fields my study requires?

    SELECT id FROM pedigrees
    WHERE doc->'meta'->'deidentified' ?& array['meta.title','pedigree.people.name','pedigree.people.dob','pedigree.people.dod'];
    
  2. Completeness check: is every PHI-capable field that is actually present covered? This is a pure function of the document (isFullyDeidentified(doc)), defined by §11.2.

  3. De-identifying export is defined and deterministic: drop every PHI-capable field that is not covered by a list. One exception: a family's meta.family id is required inside a collection, so an uncovered one is replaced by an opaque id (and listed as covered) rather than dropped, and same_as and index references to it are rewritten.

11.4 Attestation

deidentified is machine-checked coverage. attestation is human accountability and is separate:

"attestation": { "method": "safe-harbor", "by": "J. Smith, Data Steward",
                 "date": "2026-09-30", "statement": "Reviewed against 45 CFR 164.514(b)(2)." }

method: safe-harbor, expert-determination, or other. All keys optional.

11.5 Limits

12. Semantic validation

The schema cannot express these. A conforming validator reports them; the level is Error or Warning.

# Rule
V1 id unique within a family; person ids referenced by parents, siblings, couples, kin.of, index exist E
V2 At most one proband per family E
V3 At most two parents; a person is not their own ancestor E
V4 couples[].partners are two distinct people E
V5 A person with dod does not have deceased: false E
V6 health[].condition is a key of the family's pedigree.conditions E
V7 dob not after dod; parent dob before child dob W
V8 infer.chosen ∈ infer.candidates; level agrees (§7.3) E
V9 Sex of the person agrees with the last F/M step of chosen E
V10 A data reference has mediaType and a sha256 matching the decoded bytes; href xor data E
V11 Every deidentified entry is a PHI-capable field path for its scope E
V12 Every condition in a view.fill is in the same family's view.legend E
V13 index.of matches the document (§8); mismatch is not an error but means "rebuild" W
V14 A collection's meta.family ids are unique E
V15 age_at_death only on a deceased person, age only on a living one; ages agree with dob, dod and meta.as_of (within a year) W
V16 A diagnosis (onset in years) is not later than the person's age or age_at_death W
V17 laterality and receptors only on a breast cancer; location only on a colorectal cancer W
V18 risk_factors agree with themselves: no first_live_birth_age with parity 0, no menopause_age when menopausal is false, no first birth before menarche W

13. Reserved for future versions

Not specified in v0.4; the names are reserved so they are not used for something else: twins and zygosity (multiple), pregnancy and infertility (reproductive), contact, same_as semantics beyond identity, relationship status on couples (separated, divorced), and path step W.

14. Standards alignment

Concern Standard
Dates, durations ISO 8601
Canonical bytes RFC 8785 (JCS)
URIs RFC 3986
Inline binary RFC 4648 base64
Stated relationship HL7 v3 RoleCode (FHIR FamilyMemberHistory.relationship)
Condition coding FHIR Coding (system + code); ICD-10, SNOMED CT, HPO, OMIM, MONDO
Media types IANA
Link relations IANA link relations (rel)
Structure JSON Schema 2020-12
Sex M F U O → FHIR administrative-gender (male female unknown other); .PED 1 2 0 0 (O lossy)
Interchange FHIR FamilyMemberHistory, GA4GH Phenopackets (Family, Pedigree), PLINK .PED

.PED mapping. The paternal and maternal columns are derived from parents (biological parents only). The phenotype column needs a caller-supplied definition of "affected", given as a condition key or canonical key (§6.3). .PED cannot carry codings, inference, or presentation, so conversion to .PED is lossy.

15. Changelog

v0.4 (2026-10-06) — first public version of Pedigree JSON: "format": "pedigree-json/0.4", four sections (meta, pedigree, view, index), a conditions dictionary with coded conditions, kin/infer with inference levels, index, multi-family collections, deidentified and attestation, view.legend quarter-symbol fills, narrative, and references with inline base64.

16. Conformance, versioning, and openness

Conformance. A document conforms if it validates against the JSON Schema and violates no Error-level rule in §12. A writer conforms if everything it emits is a conforming document and it follows §2.1 (no null, no keys outside this specification except under ext). A reader conforms if it accepts both profiles (§9.1), preserves unknown keys when re-writing, and treats infer and index as non-authoritative.

Versioning. The format value carries major.minor. A minor version may add optional fields and values but never changes the meaning of an existing one, so a v0.4 reader can read a later v0.x document leniently (§2.1). A change of meaning requires a new major version (the leading 0 means the format is still young, but v0.4 is considered stable for implementation).

Openness. Pedigree JSON is an unformat: an open set of practices, not a product, built from ideas that should already be obvious. Anyone may use it, implement it, copy it, adapt it, and build on it, for any purpose, with no permission, fee, registration, or attribution required. You are encouraged to innovate on it: add data under ext, propose changes, or fork it. If you extend it in ways others may want, sharing what you did helps everyone, but nothing requires it.