JSContact: A JSON Representation of Contact Data
Extracted elements (34)
Id-keyed maps (Id[ObjectType]) are used instead of arrays throughout JSContact to represent unordered sets of objects. This allows concise PatchObject-based updates and enables cross-referencing between objects (e.g., Title objects referencing Organization objects by Id).
JSContact uses JSON (specifically I-JSON) rather than XML or a vCard syntax because JSON's widespread adoption lowers the barrier to adoption, and production-ready JSON implementations eliminate a whole category of parser-related interoperability issues.
Unlike jCard (a direct JSON mapping of vCard), JSContact defines its own data model and expands semantics where appropriate. This allows it to address missing vCard features (social media, pronouns, structured address components) without being constrained by vCard's structure.
JSContact is designed as an alternative to vCard (RFC 6350), jCard (RFC 7095), and xCard (RFC 6351). RFC 9554 defines new vCard properties for JSContact-specific data, and RFC 9555 defines bidirectional conversion; however, conversion need not fully preserve semantic meaning.
A patch in the localizations PatchObject MUST NOT target the localizations property itself. Localization patches MUST contain valid values for the patched property; localizations SHOULD NOT add new properties.
All JSContact data MUST be valid according to the constraints given in I-JSON (RFC 7493), a strict subset of JSON. All member names in JSON objects and all string values are case-sensitive unless explicitly stated otherwise.
Extensions MUST NOT lead to a required update of the JSContact specification. A new minor version MUST NOT require implementations to change their processing; differing major versions indicate backwards-incompatible changes and implementations MUST be prepared for them.
Implementations MUST handle a JSContact object as invalid if a type name, property name, or enumerated value only differs in case from one defined for any known JSContact version, regardless of the Card's declared version.
Implementations MUST NOT treat unknown properties (whose names adhere to IANA naming conventions) as invalid; instead they MUST preserve them in the JSContact object to allow interoperation without data loss.
Implementations MUST reject a PatchObject in its entirety if any of its patches are invalid; implementations MUST NOT apply partial patches. A patch pointer MUST NOT use '-' as an array index, and there MUST NOT be two patches where one pointer is a prefix of the other.
Implementations MUST validate IANA-registered properties and MUST reject invalid ones. IANA-registered property names MUST be in lower camel case and MUST only contain ASCII alphanumeric characters or the '@' character; control characters, colons, and quotation marks are forbidden.
Implementations MUST validate that JSON objects with the @type property conform to the specification of the named JSContact object type. An object that is not the value of a property (e.g., the topmost object in JSON data) MUST have the @type property set.
Implementations that set bidirectional text in free-form text properties MUST ensure each property value complies with the Unicode Bidirectional Algorithm. Implementations MUST NOT assume text values of adjacent properties are processed as a combined string.
In a Name object, the components property MUST be set if the full property is not set, and the component list MUST have at least one entry with a kind other than 'separator'. If isOrdered is true, implementations MUST NOT insert two consecutive separator components.
The Card uid property is mandatory. Its value SHOULD be a URN; UUID version 4 in the 'uuid' namespace is RECOMMENDED. The Card @type MUST be 'Card' and version MUST be an IANA-registered JSContact version value.
The EmailAddress 'address' property MUST be an addr-spec as defined in RFC 5322 Section 3.4.1. The pref value MUST be in the range 1–100, with 1 being most preferred; absent pref MUST be interpreted as least preferred.
The Id type MUST only contain characters from the base64url alphabet (A-Za-z0-9, hyphen, underscore), with length 1–255 octets. Id map keys MUST be preserved across multiple versions of the JSContact object.
The UTCDateTime type MUST use uppercase letters, MUST use 'Z' as the time offset, and MUST NOT include fractional seconds unless non-zero; non-zero fractional seconds MUST NOT have trailing zeros.
Vendor-specific property names MUST start with a domain-name v-prefix followed by a colon and a v-name (the 'v-extension' ABNF). Implementations MUST preserve vendor-specific properties regardless of whether they understand them and MUST NOT reject their values as invalid.
The Address object holds postal and geographic location data via an optional AddressComponent array (kinds: room, apartment, floor, building, number, name, block, subdistrict, district, locality, region, postcode, country, direction, landmark, postOfficeBox, separator) plus full, countryCode, coordinates (geo: URI), and timeZone fields.
The Card object is the root JSContact type for storing contact information. Its mandatory properties are @type (must be 'Card'), version (a registered JSContact version), and uid (unique identifier). All other properties are optional.
The Id type is a string of 1–255 octets using only base64url characters (A-Za-z0-9, '-', '_'). It is used as map keys throughout JSContact to create named, unordered sets of objects that support concise patching and cross-referencing.
The localizations property maps RFC 5646 language tags to PatchObject values, enabling language-specific alternatives for existing Card property values. Localization is applied by copying the Card (without the localizations property) and applying patches.
The Name object contains an optional components array of NameComponent objects (kind values: title, given, given2, surname, surname2, credential, generation, separator), an isOrdered flag, a full string, a sortAs map, and phoneticScript/phoneticSystem properties.
The PatchObject type (String[*]) represents a set of patches using a subset of JSON Pointer (RFC 6901) paths with an implicit leading '/'. It is used for incremental updates and as the value type for the localizations property.
The Phone object requires a 'number' property (URI or free text, e.g., 'tel:' or 'sip:' URIs) and an optional 'features' set (mobile, voice, text, video, main-number, textphone, fax, pager) indicating supported contact modalities.
The Resource base type defines common properties for URI-identified resources: @type (must be a concrete subtype name, not 'Resource'), kind, uri (mandatory URI per RFC 3986), mediaType, contexts, pref, and label. Concrete subtypes include CryptoKey, Calendar, Directory, Link, and Media.
The SpeakToAs object enables specifying grammatical gender (animate, common, feminine, inanimate, masculine, neuter) and/or pronouns (free-text, e.g., 'they/them') to direct how to address or refer to the contact; grammatical gender does not imply gender identity or assigned sex.
The JSContact Enum Values Registry tracks allowed string values for properties that restrict values to an enumerated list (e.g., kind, NameComponent kind, AddressComponent kind, Phone features). Implementations MUST only set IANA-registered or vendor-specific values for such properties.
The JSContact Properties Registry tracks all defined Card properties with fields: property name, type, version introduced, version obsoleted, and reference. It governs the lower-camel-case property names implementations must validate.
The JSContact Types Registry tracks all JSContact object type names (e.g., Card, Name, Address, EmailAddress, Phone) with fields: type name, version introduced, version obsoleted, and reference. The JSContact Version Registry tracks version strings such as '1.0'.
This document creates the 'JSContact' registry group at IANA containing four registries: JSContact Version Registry, JSContact Properties Registry, JSContact Types Registry, and JSContact Enum Values Registry. All registrations require designated expert review.
Implementations parsing JSContact data MUST be robust against malicious JSON inputs exploiting parser vulnerabilities (deeply nested objects, very large payloads, or data causing parser failures). Conformance to I-JSON (RFC 7493) reduces the attack surface.
URI values in JSContact (e.g., in Resource uri or cryptoKeys) can point to external or embedded content. Implementations must guard against SSRF, data exfiltration, and execution of malicious content embedded in data: URIs when fetching or rendering these values.