RFC 9555

JSContact: Converting from and to vCard

πŸ“… published May 2024, from ietf

RFC 9555: JSContact: Converting from and to vCard πŸ’Œβœ¨

Okay bestie, this is the RFC that teaches JSContact and vCard to talk to each other. 🫢 Here's the title block, all the details up top:

  • Stream: Internet Engineering Task Force (IETF) 🌸
  • RFC number: 9555 πŸŽ€
  • Authors: M. Loffredo (IIT-CNR/Registro.it) and R. Stepanek (Fastmail) πŸ‘―
  • Category: Standards Track πŸ‘‘
  • Date: May 2024 πŸ“…
  • ISSN: 2070-1721 πŸ¦‹
  • Updates: 6350 (so it's an update to RFC 6350, the vCard spec) πŸ”₯
  • Obsoletes: nothing is listed in this header πŸ™ˆ

Abstract 🧚

This doc is all about how to convert contact info between the JSContact and vCard data formats. It sets conversion rules for every JSContact and vCard element that was registered at IANA when it was published, so no element gets left out πŸ’…. It also defines brand-new JSContact properties and vCard properties and parameters. Those exist so you can convert arbitrary or unknown JSContact and vCard elements too, even the weird ones πŸ’€βœ¨.

Status of This Memo 🌈

This is an Internet Standards Track document, so it's official-official πŸ‘‘.

It's a product of the Internet Engineering Task Force (IETF), and it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 7841 🫢.

You can find the current status of this document, any errata, and how to send feedback at https://www.rfc-editor.org/info/rfc9555 πŸ“¬.

Copyright (c) 2024 IETF Trust and the people listed as the document authors. All rights reserved πŸ’œ.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info), as they stand on the publication date. Please read these carefully, because they spell out your rights and restrictions for this document πŸ“œ. Code components pulled out of this document have to include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, just like the Revised BSD License says βš–οΈ.

This document might include material from IETF Documents or IETF Contributions that were published or made publicly available before November 10, 2008. The people who control the copyright in some of that material may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process πŸ™ˆ. Unless you get a proper license from those copyright holders, this document can't be modified outside the IETF Standards Process, and derivative works of it can't be made outside the IETF Standards Process either. The one exceptions are formatting it for publication as an RFC or translating it into languages other than English 🌍.

Table of Contents πŸ“š

1.  Introduction
  1.1.  Motivation
  1.2.  Notational Conventions
  1.3.  ABNF Notations
2.  Converting vCard to JSContact
  2.1.  General Rules
    2.1.1.  The Card uid Property
    2.1.2.  Choosing Identifiers
  2.2.  vCard Value Data Types
    2.2.1.  BOOLEAN
    2.2.2.  DATE, TIME, DATE-TIME, DATE-AND-OR-TIME, and TIMESTAMP
    2.2.3.  INTEGER
    2.2.4.  FLOAT
    2.2.5.  LANGUAGE-TAG
    2.2.6.  TEXT
    2.2.7.  URI
    2.2.8.  UTC-OFFSET
  2.3.  vCard Parameters
    2.3.1.  ALTID
    2.3.2.  AUTHOR
    2.3.3.  AUTHOR-NAME
    2.3.4.  CALSCALE
    2.3.5.  CC
    2.3.6.  CREATED
    2.3.7.  DERIVED
    2.3.8.  GEO
    2.3.9.  GROUP
    2.3.10. INDEX
    2.3.11. LANGUAGE
    2.3.12. LABEL
    2.3.13. LEVEL
    2.3.14. MEDIATYPE
    2.3.15. PHONETIC
    2.3.16. PID
    2.3.17. PREF
    2.3.18. PROP-ID
    2.3.19. SCRIPT
    2.3.20. SERVICE-TYPE
    2.3.21. SORT-AS
    2.3.22. TYPE
    2.3.23. TZ
    2.3.24. USERNAME
    2.3.25. VALUE
  2.4.  General Properties
    2.4.1.  BEGIN and END
    2.4.2.  KIND
    2.4.3.  SOURCE
    2.4.4.  XML
  2.5.  Identification Properties
    2.5.1.  ANNIVERSARY, BDAY, BIRTHPLACE, DEATHDATE, and
            DEATHPLACE
    2.5.2.  FN
    2.5.3.  GENDER
    2.5.4.  GRAMGENDER and PRONOUNS
    2.5.5.  N
    2.5.6.  NICKNAME
    2.5.7.  PHOTO
  2.6.  Delivery Addressing Properties
    2.6.1.  ADR
  2.7.  Communications Properties
    2.7.1.  EMAIL
    2.7.2.  IMPP
    2.7.3.  LANG
    2.7.4.  LANGUAGE
    2.7.5.  SOCIALPROFILE
    2.7.6.  TEL
  2.8.  Geographical Properties
    2.8.1.  GEO
    2.8.2.  TZ
    2.8.3.  Combining Geographical Properties
  2.9.  Organizational Properties
    2.9.1.  CONTACT-URI
    2.9.2.  LOGO
    2.9.3.  MEMBER
    2.9.4.  ORG
    2.9.5.  RELATED
    2.9.6.  TITLE and ROLE
  2.10. Personal Information Properties
    2.10.1.  EXPERTISE
    2.10.2.  HOBBY
    2.10.3.  INTEREST
    2.10.4.  ORG-DIRECTORY
  2.11. Explanatory Properties
    2.11.1.  CATEGORIES
    2.11.2.  CLIENTPIDMAP
    2.11.3.  CREATED
    2.11.4.  NOTE
    2.11.5.  PRODID
    2.11.6.  REV
    2.11.7.  SOUND
    2.11.8.  UID
    2.11.9.  URL
    2.11.10. VERSION
    2.11.11. X-ABLabel
  2.12. Security Properties
    2.12.1.  KEY
  2.13. Calendar Properties
    2.13.1.  CALADRURI
    2.13.2.  CALURI
    2.13.3.  FBURL
  2.14. Extended Properties and Parameters
  2.15. New JSContact Properties
    2.15.1.  vCardProps
    2.15.2.  vCardParams
    2.15.3.  vCardName
3.  Converting JSContact to vCard
  3.1.  Conversion Rules
    3.1.1.  Converting Unknown Properties
  3.2.  New vCard Properties
    3.2.1.  JSPROP
  3.3.  New vCard Parameters
    3.3.1.  JSCOMPS
    3.3.2.  JSPTR
4.  Security Considerations
5.  IANA Considerations
  5.1.  New vCard Property
  5.2.  New vCard Parameter
  5.3.  New JSContact Properties
  5.4.  New JSContact Type
6.  References
  6.1.  Normative References
  6.2.  Informative References
Appendix A.  Reverse Rules of Converting a vCard to a JSContact
        Card
Acknowledgements
Authors' Addresses

1. Introduction 🌸

1.1. Motivation πŸ’­

The JSContact data model and format [RFC9553] wants to be an alternative to the super popular vCard standard [RFC6350] and the jCard format [RFC7095] πŸ‘‘.

Apps might prefer JSContact for swapping contact card data with other systems, but they'll probably still need to talk to services and clients that only speak vCard or jCard πŸ“±. On the flip side, existing contact data providers and consumers who already use vCard or jCard might want to show their contact data in JSContact too πŸ¦‹.

So this doc sets up standard rules for converting contact data between JSContact and vCard, and by extension jCard, so everyone can get along 🫢✨.

1.2. Notational Conventions πŸ“

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here πŸ”₯.

1.3. ABNF Notations 🧩

The ABNF definitions in this doc use the notations of [RFC5234]. Any ABNF rules that aren't defined here are defined in either [RFC5234] (for things like CRLF, WSP, DQUOTE, VCHAR, ALPHA, and DIGIT) or [RFC6350] πŸ“.

2. Converting vCard to JSContact πŸ’–

This section has the conversion rules from the vCard to the JSContact Card πŸ’…. It follows the same structure as vCard v4 [RFC6350]. Properties and parameters from vCard extension RFCs, including the ones in "vCard Format Extension for JSContact" [RFC9554], have been added to the matching subsections 🌈.

2.1. General Rules πŸŽ€

2.1.1. The Card uid Property πŸ”‘

The UID property (Section 6.7.6 of [RFC6350]) in vCard is optional, but the Card object's uid property (Section 2.1.9 of [RFC9553]) is mandatory πŸ₯Ί. So implementations that convert a vCard without a UID property MUST generate a unique identifier to use as the value for the uid property. This value SHOULD stay the same when you convert the same vCard multiple times, but how you pull that off is up to each implementation πŸ€”βœ¨.

2.1.2. Choosing Identifiers πŸͺͺ

Multivalued properties in JSContact are usually represented as a JSON object, where the object keys are of the Id type (Section 1.4.1 of [RFC9553]) and the object values are the converted vCard property 🧁. If there's no PROP-ID parameter (see Section 2.3.18), implementations are free to pick any identifier they want as the key for those entries πŸ’œ. Whatever identifier generation scheme an implementation uses, it MUST generate values that are valid according to the definition of the Id type in [RFC9553] πŸ™Œ. For example, it could be an incrementing number across all identifier keys in the Card object, or it could just be unique within one JSON object πŸ¦‹.

2.2. vCard Value Data Types πŸ’Ž

2.2.1. BOOLEAN βœ…

The BOOLEAN type (Section 4.4 of [RFC6350]) converts to the JSContact Boolean type (Section 1.3.2 of [RFC9553]) πŸ’«.

2.2.2. DATE, TIME, DATE-TIME, DATE-AND-OR-TIME, and TIMESTAMP πŸ“…

The TIMESTAMP type (Section 4.3.5 of [RFC6350]) converts to the UTCDateTime type (Section 1.4.5 of [RFC9553]), except for anniversaries. For anniversaries, it converts to the Timestamp type (Section 2.8.1 of [RFC9553]) πŸŽ‚.

The DATE type (Section 4.3.1 of [RFC6350]) converts to a PartialDate object (Section 2.8.1 of [RFC9553]) when it's used for an anniversary, unless the DATE value only has a month or a day (but not both) πŸŒ™.

These temporal types don't convert to a JSContact datetime type. Instead, vCard properties or parameters that have these value types convert as defined in Section 2.15 🧚:

  • TIME (Section 4.3.2 of [RFC6350])
  • DATE-TIME (Section 4.3.3 of [RFC6350])
  • DATE-AND-OR-TIME (Section 4.3.4 of [RFC6350])
  • DATE type values that only define a month or day (but not both)

2.2.3. INTEGER πŸ”’

The INTEGER type (Section 4.5 of [RFC6350]) converts to the JSContact Int and UnsignedInt types (Section 1.4.2 of [RFC9553]) πŸ’•.

2.2.4. FLOAT 🌊

The FLOAT type (Section 4.6 of [RFC6350]) converts to the JSContact Number type (Section 1.3.2 of [RFC9553]) ✨.

2.2.5. LANGUAGE-TAG 🌍

The LANGUAGE-TAG type (Section 4.8 of [RFC6350]) converts to the JSContact String type (Section 1.3.2 of [RFC9553]). The value MUST be a language tag as defined in [RFC5646] πŸ—£οΈ.

2.2.6. TEXT πŸ“

The TEXT type (Section 4.1 of [RFC6350]) converts to the JSContact String type (Section 1.3.2 of [RFC9553]) 🍭.

2.2.7. URI πŸ”—

The URI type (Section 4.2 of [RFC6350]) converts to the JSContact String type (Section 1.3.2 of [RFC9553]). The value MUST be a URI as defined in Section 3 of [RFC3986] 🌐.

2.2.8. UTC-OFFSET πŸ•°οΈ

The UTC-OFFSET type (Section 4.7 of [RFC6350]) either converts to a String value containing an IANA Time Zone Database entry name (see Section 2.8.2), or it doesn't convert to any JSContact type at all. For the second case, vCard properties or parameters with these values convert as defined in Section 2.15 🌏.

2.3. vCard Parameters πŸŽ›οΈ

This section has the conversion rules for vCard parameters. A rule usually only applies to specific vCard properties. To convert a vCard parameter on an arbitrary vCard property, check out Section 2.15.2 🧸.

2.3.1. ALTID πŸͺ„

The ALTID parameter (Section 5.4 of [RFC6350]) doesn't convert to an IANA-registered property in JSContact. Instead, several conversion rules use this parameter to combine multiple vCard properties into a single JSContact object instance 🧩. For an example of that, see Section 2.6.1. To keep the verbatim value of the ALTID parameter, set the JSContact properties defined in Section 2.15 πŸ’œ.

2.3.2. AUTHOR πŸ–‹οΈ

Okay bestie, the AUTHOR parameter (Section 4.1 of [RFC9554]) on a NOTE property turns into the Author object's uri property (Section 2.8.3 of [RFC9553]) πŸ’Œ Then that Author object gets set as the value of the Note object's author property (Section 2.8.3 of [RFC9553]). Main character energy!

2.3.3. AUTHOR-NAME πŸ’β€β™€οΈ

The AUTHOR-NAME parameter (Section 4.2 of [RFC9554]) on a NOTE property converts to the Author object's name property (Section 2.8.3 of [RFC9553]). And yep, that Author object is set as the value of the Note object's author property too. Iconic πŸ‘‘

2.3.4. CALSCALE πŸ“…

The CALSCALE parameter (Section 5.8 of [RFC6350]) set on a BDAY, DEATHDATE, or ANNIVERSARY property converts to the PartialDate object's calendarScale property (Section 2.8.1 of [RFC9553]) πŸ—“οΈ

2.3.5. CC 🌍

The CC parameter (Section 3.1 of [RFC8605]) on an ADR property converts to the Address object's countryCode property (Section 2.5.1.1 of [RFC9553]). Country codes, but make it organized πŸ’…

2.3.6. CREATED ⏰

The CREATED parameter (Section 4.3 of [RFC9554]) on a NOTE property converts to the Note object's created property (Section 2.8.3 of [RFC9553]). Timestamp slay πŸ¦‹

2.3.7. DERIVED πŸ™ˆ

Okay so the DERIVED parameter (Section 4.4 of [RFC9554]) does not convert to JSContact at all 😭 If the DERIVED parameter is set to "true" on a vCard property, then implementations MAY choose not to convert that property. It's a choice, not a rule, so you're free to decide πŸ’œ

2.3.8. GEO πŸ—ΊοΈ

The GEO parameter (Section 5.10 of [RFC6350]) set on an ADR property converts to the Address object's coordinates property (Section 2.5.1.1 of [RFC9553]). Pinned, bestie πŸ“

2.3.9. GROUP 🧚

The GROUP parameter (Section 7.1 of [RFC7095]) does not convert to JSContact. Its whole deal is jCard, and it MUST NOT be set in a vCard. Don't be that person πŸ™…β€β™€οΈ

Okay, now the lowkey important bit: you do NOT need to keep the exact group name when you go from vCard to JSContact and back again. Any group identifiers will do, as long as the resulting vCard still groups its properties the same way the original did. The grouping is the vibe, not the label πŸŽ€

If you still want the exact group name on a vCard property, implementations MAY set the jCard "group" parameter in the JSContact properties vCardProps or vCardParams, as defined in Section 2.15. Here's how that looks:

item1.TEL;VALUE=uri:tel:+1-555-555-5555
"phones": {
  "p1": {
    "number": "tel:+1-555-555-5555",
    "vCardParams" : {
     "group" : "item1"
    }
  }
}

Figure 1: Example of How to Preserve the Group Name in vCardParams during Conversion

item2.X-FOO:bar
"vCardProps": [
  ["x-foo", {
    "group": "item2"
  }, "unknown", "bar"]
]

Figure 2: Example of How to Preserve the Group Name in vCardProps during Conversion

2.3.10. INDEX πŸ—‚οΈ

The INDEX parameter (Section 3.1 of [RFC6715]) set on the EXPERTISE, HOBBY, INTEREST, and ORG-DIRECTORY properties converts to the PersonalInfo (Section 2.8.4 of [RFC9553]) and Directory (Section 2.6.2 of [RFC9553]) objects' listAs property. Sorted and serving ✨

2.3.11. LANGUAGE 🌏

The LANGUAGE parameter (Section 5.1 of [RFC6350]) converts to an entry in the Card object's localizations property (Section 2.7.1 of [RFC9553]) for that vCard property the parameter is set on. The value of the LANGUAGE parameter becomes the language tag key in the localizations property. Multilingual and unbothered 🫢

Now, this spec does NOT give you one standard rule for converting the property values. Building the localizations value is up to the implementation, so it's a little choose-your-own-adventure πŸ“– Two options to populate the localizations property are:

  • One Patch per Property: For each vCard property with a LANGUAGE parameter, set the complete path in the PatchObject to the JSContact property that the vCard property converts to. The value of the patch is the converted property value. This is simple to process and adequate if the vCard only contains a few properties with the LANGUAGE parameter. Easy mode 🌸
  • Bundle Patches by Parent: If a PatchObject contains multiple paths that have the same parent paths, then it might be possible to combine these patches into one patch that patches the parent property. This is possible if the property in the Card is patched in its entirety. Big brain move 🧠

Generally, localizations only localize properties that are present in the non-localized version of this Card. Figure 3 shows what that looks like:

FN;LANGUAGE=EN:John Doe
TITLE;ALTID=1;LANGUAGE=EN:Boss
TITLE;ALTID=1;LANGUAGE=fr:Patron
"language": "en",
"name": {
  "full": "John Doe"
},
"titles": {
  "t1": {
    "name": "Boss"
  }
},
"localizations": {
  "fr": {
    "titles/t1/name": "Patron"
  }
}

Figure 3: LANGUAGE Conversion Example: One Dominant Language

As a special case, if one or more vCard properties of the same type do NOT have the LANGUAGE parameter set, add them to the non-localized Card. Convert any with LANGUAGE parameters to the localizations property. Figure 4 has the deets:

FN:John Doe
TITLE;ALTID=1:Boss
TITLE;ALTID=1;LANGUAGE=fr:Patron
"name": {
  "full": "John Doe"
},
"titles": {
  "t1": {
    "name": "Boss"
  }
},
"localizations": {
  "fr": {
    "titles/t1/name": "Patron"
  }
}

Figure 4: LANGUAGE Conversion Example: Property without Language

2.3.12. LABEL 🏷️

The LABEL parameter (Section 6.3.1 of [RFC6350]) on an ADR property converts to the Address object's full property (Section 2.5.1.1 of [RFC9553]). Full address, full send πŸ’Œ

2.3.13. LEVEL πŸ“Ά

The LEVEL parameter (Section 3.2 of [RFC6715]) converts to the PersonalInfo object's level property (Section 2.8.4 of [RFC9553]). If this parameter is set on the EXPERTISE property, then its values convert like this:

  • "beginner" converts to "low";
  • "average" converts to "medium"; and
  • "expert" converts to "high".

In all other cases, the values convert verbatim, but lowercase MUST be used for the JSContact value. Lowercase is the only way, babe πŸ™

2.3.14. MEDIATYPE πŸ“Ž

The MEDIATYPE parameter (Section 5.7 of [RFC6350]) converts to the Resource object's mediaType property (Section 1.4.4 of [RFC9553]). File types, served πŸ“

2.3.15. PHONETIC πŸ—£οΈ

The PHONETIC parameter (Section 4.6 of [RFC9554]) converts to the phoneticSystem property of the Name (Section 2.2.1 of [RFC9553]) and Address (Section 2.5.1 of [RFC9553]) objects, UNLESS the parameter value is "script". In that case, the phoneticSystem property is not set at all πŸ™ˆ

The value of the SCRIPT parameter converts to the phoneticScript property (see Section 2.3.19).

The related N or ADR property is defined by the vCard ALTID parameter. The conversion rules for the N (Section 2.5.5) and ADR (Section 2.6.1) properties define how the vCard components convert to JSContact.

The component values of the property the PHONETIC parameter is set on convert to the respective NameComponent or AddressComponent objects' phonetic properties.

If more than one property has the PHONETIC parameter set and they all relate to the same property, then they convert to the Card object's localizations property according to their LANGUAGE parameter values, as outlined in Section 2.3.11. Figure 5 is a whole thing:

LANGUAGE=zh-Hant
N;ALTID=1;LANGUAGE=zh-Hant:ε­«;δΈ­ε±±;ζ–‡,ι€Έδ»™;;
N;ALTID=1;PHONETIC=jyut;
  SCRIPT=Latn;LANGUAGE=yue:syun1;zung1saan1;man4,jat6sin1;;
"language": "zh-Hant",
"name": {
  "components": [
    { "kind": "surname", "value": "ε­«" },
    { "kind": "given", "value": "δΈ­ε±±" },
    { "kind": "given2", "value": "ζ–‡" },
    { "kind": "given2", "value": "ι€Έδ»™" }
  ]
},
"localizations": {
  "yue": {
    "name/phoneticSystem": "jyut",
    "name/phoneticScript": "Latn",
    "name/components/0/phonetic": "syun1",
    "name/components/1/phonetic": "zung1saan1",
    "name/components/2/phonetic": "man4",
    "name/components/3/phonetic": "jat6sin1"
  }
}

Figure 5: PHONETIC Conversion Example

2.3.16. PID πŸ”’

The PID parameter (Section 5.5 of [RFC6350]) converts to the vCardParams property; see Section 2.15.2. Receipts kept 🧾

2.3.17. PREF ⭐

The PREF parameter (Section 5.3 of [RFC6350]) converts to the pref property of the derived JSContact object. Preferred, obviously πŸ’–

2.3.18. PROP-ID πŸͺͺ

The PROP-ID parameter (Section 4.7 of [RFC9554]) converts to the Id-typed key of the derived JSContact object. Every property gets its own name tag 🏷️ Figure 6 shows it:

TEL;PROP-ID=PHONE-A;VALUE=uri;PREF=1;TYPE="voice,home"
  :tel:+1-555-555-5555;ext=5555
TEL;PROP-ID=PHONE-B;VALUE=uri;TYPE=home
  :tel:+33-01-23-45-67
"phones": {
  "PHONE-A": {
    "contexts": { "private": true },
    "features": { "voice": true },
    "number": "tel:+1-555-555-5555;ext=5555",
    "pref": 1
  },
  "PHONE-B": {
    "contexts": { "private": true },
    "number": "tel:+33-01-23-45-67"
  }
}

Figure 6: PROP-ID Conversion Example

2.3.19. SCRIPT ✍️

The SCRIPT parameter (Section 4.8 of [RFC9554]) converts to the phoneticScript property of the Name (Section 2.2.1 of [RFC9553]) or Address (Section 2.5.1 of [RFC9553]) objects.

Also see Section 2.3.15. Go check it out, it's connected πŸ”—

2.3.20. SERVICE-TYPE πŸ›œ

The SERVICE-TYPE parameter (Section 4.9 of [RFC9554]) converts to the OnlineService object's service property (Section 2.3.2 of [RFC9553]). Online service, but make it a whole service πŸ’€

2.3.21. SORT-AS πŸ”€

The SORT-AS parameter (Section 5.9 of [RFC6350]) converts to the sortAs properties of the Name, Organization, and OrgUnit objects. Alphabetized, no cap πŸ“š

2.3.22. TYPE 🎭

The TYPE parameter (Section 5.6 of [RFC6350]) converts to either the contexts property or the kind property, depending on the sections defined later on. If not otherwise specified, the vCard "home" and "work" parameter values convert to the JSContact "private" and "work" contexts, respectively. Home is where the contexts are 🏠

2.3.23. TZ πŸ•°οΈ

The TZ parameter (Section 5.11 of [RFC6350]) on an ADR property converts to the Address object's timeZone property (Section 2.5.1.1 of [RFC9553]). Also see the conversion of the TZ property in Section 2.8.2. Time zones, bestie, time zones ⏳

2.3.24. USERNAME πŸ§‘β€πŸ’»

The USERNAME parameter (Section 4.10 of [RFC9554]) converts to the OnlineService object's user property (Section 2.3.2 of [RFC9553]). Username, who dis 😌

2.3.25. VALUE πŸŽ€

The VALUE parameter (Section 5.2 of [RFC6350]) does not convert to an IANA-registered property in JSContact. If you want to keep properties with experimental values, see Sections 2.15.1 and 2.15.2. Experimental, but make it safe πŸ§ͺ

2.4. General Properties 🌷

2.4.1. BEGIN and END 🎬

The BEGIN and END properties do not convert to IANA-registered properties in JSContact. Start, end, that's the whole story 🎬

2.4.2. KIND πŸ‘‘

The KIND property (Section 6.1.4 of [RFC6350]) converts to the kind property (Figure 7). Allowed values are the ones described in Section 6.1.4 of [RFC6350], extended with the values declared in [RFC6473] and [RFC6869]. Figure 7 shows it, no cap:

KIND:individual
"kind": "individual"

Figure 7: KIND Conversion Example

2.4.3. SOURCE πŸ“‚

The SOURCE property (Section 6.1.3 of [RFC6350]) converts to a Directory object (Section 2.6.2 of [RFC9553]) in the Card object's directories property (Figure 8). The Directory object's kind property is set to "entry", and its uri property is set to the SOURCE property value. Source of truth energy 🫢

The PREF and MEDIATYPE parameters convert according to the rules defined in Section 2.3.

SOURCE:https://dir.example.com/addrbook/jdoe/Jean%20Dupont.vcf
"directories": {
   "ENTRY-1": {
     "kind": "entry",
     "uri": "https://dir.example.com/addrbook/jdoe/Jean%20Dupont.vcf"
   }
}

Figure 8: SOURCE Conversion Example

2.4.4. XML 🫧

The XML property (Section 6.1.5 of [RFC6350]) converts to the vCardProps property; see Section 2.15.1. Extra XML, extra vibes πŸ’œ

2.5. Identification Properties πŸͺž

2.5.1. ANNIVERSARY, BDAY, BIRTHPLACE, DEATHDATE, and DEATHPLACE πŸŽ‚

okay so these five properties all turn into Anniversary objects inside the Card object's anniversaries property (Figure 9) πŸŽ€

  • ANNIVERSARY (Section 6.2.6 of [RFC6350])
  • BDAY (Section 6.2.5 of [RFC6350])
  • BIRTHPLACE (Section 2.1 of [RFC6474])
  • DEATHDATE (Section 2.3 of [RFC6474])
  • DEATHPLACE (Section 2.2 of [RFC6474])

BDAY and BIRTHPLACE convert to an Anniversary object (Section 2.8.1 of [RFC9553]) with the date and place properties set. The kind property is set to "birth" 🍼

DEATHDATE and DEATHPLACE convert to an Anniversary object with the date and place properties set. The Anniversary object's kind property is set to "death" πŸ•ŠοΈ

ANNIVERSARY converts to the Anniversary object's date property. The Anniversary object's kind property is set to "wedding" πŸ’’

If the BIRTHPLACE or DEATHPLACE property value is of type URI using the "geo:" URI scheme, then it converts to the Address object's coordinates property. If the value type is TEXT, then it converts to the Address object's full property. Otherwise, it converts to the vCardProps property; see Section 2.15.1 ✨

The ALTID and LANGUAGE parameters of both the BIRTHPLACE and DEATHPLACE properties convert according to the rules defined in Section 2.3 πŸ’…

BDAY:19531015T231000Z
BIRTHPLACE:
 123 Main Street\nAny Town, CA 91921-1234\nU.S.A.
DEATHDATE:19960415
DEATHPLACE:
 5 Court Street\nNew England, ND 58647\nU.S.A.
ANNIVERSARY:19860201
"anniversaries": {
  "ANNIVERSARY-1" : {
    "kind": "birth",
    "date": {
      "@type": "Timestamp",
      "utc": "1953-10-15T23:10:00Z"
    },
    "place": {
      "full":
         "123 Main Street\nAny Town, CA 91921-1234\nU.S.A."
    }
  },
  "ANNIVERSARY-2" : {
    "kind": "death",
    "date": {
      "year": 1996,
      "month": 4,
      "year": 15
    },
    "place": {
      "full": "5 Court Street\nNew England, ND 58647\nU.S.A."
    }
  },
  "ANNIVERSARY-3" : {
    "kind": "wedding",
    "date": {
      "year": 1986,
      "month": 2,
      "day": 1
    }
  }
}

       Figure 9: ANNIVERSARY, BDAY, BIRTHPLACE, DEATHDATE, and
                    DEATHPLACE Conversion Example

2.5.2. FN

The FN property (Section 6.2.1 of [RFC6350]) converts to the Name object's full property (Figure 10) 🌸 If the LANGUAGE parameter is set, then the FN property converts as outlined in Section 2.3.11. In the unexpected case where the vCard contains more than one FN property without the LANGUAGE parameter, convert the FN property that has the least parameters. If multiple such FN properties are present, choose any of them. All other FN properties convert to the vCardProps (Section 2.15.1) property 🧚

FN:John Q. Public, Esq.
"name": {
  "full": "John Q. Public, Esq."
}

                   Figure 10: FN Conversion Example

2.5.3. GENDER

The GENDER property (Section 6.2.7 of [RFC6350]) does not convert to an IANA-registered property in JSContact. To convert this property, see Section 2.15.1. Alternatively, the Card object's speakToAs property defines how to address and refer to an individual represented by the Card, as do the newly defined vCard GRAMGENDER and PRONOUNS properties of [RFC9554] 🫢

2.5.4. GRAMGENDER and PRONOUNS

The GRAMGENDER property (Section 3.2 of [RFC9554]) converts to the SpeakToAs object's grammaticalGender property (Figure 11) 🌈

The PRONOUNS property (Section 3.4 of [RFC9554]) converts to the SpeakToAs object's pronouns property (Figure 11) πŸ’œ

GRAMGENDER:NEUTER
PRONOUNS;PREF=2:they/them
PRONOUNS;PREF=1:xe/xir
"speakToAs": {
  "grammaticalGender": "neuter",
  "pronouns": {
    "PRONOUNS-1": {
      "pronouns": "they/them",
      "pref": 2
    },
    "PRONOUNS-2": {
      "pronouns": "xe/xir",
      "pref": 1
    }
  }
}

        Figure 11: GRAMGENDER and PRONOUNS Conversion Example

2.5.5. N

The N property (Section 6.2.2 of [RFC6350]) converts to a Name object (Section 2.2.1 of [RFC9553]) in the Card object's name property. Each component in the N property structured value converts to a NameComponent in the Name object's components property. The following table shows this relation πŸ¦‹

    +============+===============+==============================+
    | N          | NameComponent | Remarks                      |
    | component  | kind          |                              |
    +============+===============+==============================+
    | Family     | surname       | To vCard: add any "surname2" |
    | name       |               | NameComponent to the Family  |
    |            |               | name component, after all    |
    |            |               | "surname" values.            |
    |            |               | From vCard: ignore any value |
    |            |               | that also occurs in the      |
    |            |               | Secondary surname component. |
    +------------+---------------+------------------------------+
    | Given name | given         |                              |
    +------------+---------------+------------------------------+
    | Additional | given2        |                              |
    | name       |               |                              |
    +------------+---------------+------------------------------+
    | Honorific  | title         |                              |
    | prefix     |               |                              |
    +------------+---------------+------------------------------+
    | Honorific  | credential    | To vCard: add any            |
    | suffix     |               | "generation" NameComponent   |
    |            |               | to the Honorific suffix      |
    |            |               | component.                   |
    |            |               | From vCard: ignore any value |
    |            |               | that also occurs in the      |
    |            |               | Generation component.        |
    +------------+---------------+------------------------------+
    | Secondary  | surname2      |                              |
    | surname    |               |                              |
    +------------+---------------+------------------------------+
    | Generation | generation    |                              |
    +------------+---------------+------------------------------+

                   Table 1: N Components Conversion

If the JSCOMPS (Section 3.3.1) parameter is set, then the Name object's isOrdered property value is "true", and the defaultSeparator property and any "separator" NameComponent objects are set according to the parameter value. The order in the components property MUST adhere to the order of the JSCOMPS parameter value πŸŽ€

If the JSCOMPS parameter is not set, then the Name object's isOrdered property value is "false", and the defaultSeparator property MUST NOT be set. The order in the components property MUST follow the order of values in the N structured value when read from left to right πŸ™ˆ

If the SORT-AS parameter is set, then its structured value converts to the Name object's sortAs property according to Table 1. An empty or non-existent component value indicates that no sort is defined for this kind ✨

N;SORT-AS="Stevenson,John Philip":
 Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.;;Jr.
"name": {
  "components":[
    { "kind": "surname", "value": "Stevenson" },
    { "kind": "given", "value": "John" },
    { "kind": "given2", "value": "Philip" },
    { "kind": "given2", "value": "Paul" },
    { "kind": "title", "value": "Dr." },
    { "kind": "credential", "value": "M.D." },
    { "kind": "credential", "value": "A.C.P." },
    { "kind": "generation", "value": "Jr." }
  ],
  "sortAs": {
    "surname": "Stevenson",
    "given": "John Philip"
  }
}

                   Figure 12: N Conversion Example

See Section 3.3.1 for examples of using the JSCOMPS parameter for vCard-structured property values πŸ’–

2.5.6. NICKNAME

The NICKNAME property (Section 6.2.3 of [RFC6350]) converts to a Nickname object (Section 2.2.2 of [RFC9553]) in the Card object's nicknames property (Figure 13). The name property is set to the NICKNAME property value πŸ“

The PREF and TYPE parameters convert according to the rules defined in Section 2.3 🌸

NICKNAME:Johnny
"nicknames": {
   "NICK-1": {
    "name": "Johnny"
   }
}

                Figure 13: NICKNAME Conversion Example

2.5.7. PHOTO

The PHOTO property (Section 6.2.4 of [RFC6350]) converts to a Media object (Section 2.6.4 of [RFC9553]) in the Card object's media property (Figure 14). The Media object's kind property is set to "photo" and the uri property is set to the PHOTO value πŸ“Έ

The PREF and MEDIATYPE parameters convert according to the rules defined in Section 2.3 πŸ¦‹

PHOTO:https://www.example.com/pub/photos/jqpublic.gif
"media": {
   "PHOTO-1": {
     "kind": "photo",
     "uri": "https://www.example.com/pub/photos/jqpublic.gif"
   }
}

                 Figure 14: PHOTO Conversion Example

2.6. Delivery Addressing Properties πŸ“¬

2.6.1. ADR ✨

okay so ADR is the address property 🏠 (Section 6.3.1 of [RFC6350]), and it turns into an Address object (Section 2.5.1.1 of [RFC9553]) inside the Card object's addresses property πŸ’Œ. Each component in the ADR-structured value gets its own AddressComponent in the Address object's components property, so it's giving very organized πŸ“¦

[RFC9554] defines new components for the ADR property. Implementations SHOULD set these new components, even if all their values are the empty string 🫢

here's the big mapping of ADR components to AddressComponent kinds πŸ—ΊοΈ

    +=============+==================+===============================+
    | ADR         | AddressComponent | Remarks                       |
    | component   | kind             |                               |
    +=============+==================+===============================+
    | post office | postOfficeBox    | [RFC6350] recommends that     |
    | box         |                  | this component not be set,    |
    |             |                  | but this is now disputable    |
    |             |                  | given the new components.     |
    |             |                  | Instead, set this component   |
    |             |                  | and use the new ADR value     |
    |             |                  | format defined in [RFC9554].  |
    +-------------+------------------+-------------------------------+
    | extended    | apartment        | To vCard: set the values of   |
    | address     |                  | the following components:     |
    |             |                  |                               |
    |             |                  | *  room                       |
    |             |                  |                               |
    |             |                  | *  floor                      |
    |             |                  |                               |
    |             |                  | *  apartment                  |
    |             |                  |                               |
    |             |                  | *  building                   |
    |             |                  |                               |
    |             |                  | From vCard: ignore if the ADR |
    |             |                  | structured value is of the    |
    |             |                  | format defined in [RFC9554].  |
    |             |                  | Otherwise, convert to         |
    |             |                  | "apartment".                  |
    +-------------+------------------+-------------------------------+
    | street      | name             | To vCard: set the values of   |
    | address     |                  | the following components:     |
    |             |                  |                               |
    |             |                  | *  number                     |
    |             |                  |                               |
    |             |                  | *  name                       |
    |             |                  |                               |
    |             |                  | *  block                      |
    |             |                  |                               |
    |             |                  | *  direction                  |
    |             |                  |                               |
    |             |                  | *  landmark                   |
    |             |                  |                               |
    |             |                  | *  subdistrict                |
    |             |                  |                               |
    |             |                  | *  district                   |
    |             |                  |                               |
    |             |                  | From vCard: ignore if the ADR |
    |             |                  | structured value is of the    |
    |             |                  | format defined in [RFC9554].  |
    |             |                  | Otherwise, convert to "name". |
    +-------------+------------------+-------------------------------+
    | locality    | locality         |                               |
    +-------------+------------------+-------------------------------+
    | region      | region           |                               |
    +-------------+------------------+-------------------------------+
    | postal code | postcode         |                               |
    +-------------+------------------+-------------------------------+
    | apartment   | apartment        | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | block       | block            | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | building    | building         | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | direction   | direction        | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | district    | district         | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | floor       | floor            | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | landmark    | landmark         | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | room        | room             | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+
    | street      | number           | Defined in [RFC9554].         |
    | number      |                  |                               |
    +-------------+------------------+-------------------------------+
    | subdistrict | subdistrict      | Defined in [RFC9554].         |
    +-------------+------------------+-------------------------------+

                    Table 2: ADR Components Conversion

okay now the JSCOMPS (Section 3.3.1) parameter, which is the ordering one πŸŽ€. If it's set, the Address object's isOrdered property is "true", and the defaultSeparator property plus any separator name components get set to match the parameter value. The order in the components property MUST adhere to the order of the JSCOMPS parameter value 🎯

if JSCOMPS is not set, then isOrdered is "false" and defaultSeparator MUST NOT be set πŸ™…β€β™€οΈ and the components order MUST follow the order of the ADR structured value, read left to right ➑️

the LABEL parameter converts to the Address object's full property 🏷️

the GEO parameter converts to the Address object's coordinates property πŸ“

the TZ parameter converts to the Address object's timeZone property πŸ•°οΈ

the CC parameter converts to the Address object's countryCode property 🌍

PREF and TYPE convert by the rules in Section 2.3. the ADR-specific TYPE values from Sections 5.1 and 5.2 of [RFC9554] convert to the matching entries of the contexts property, as defined in Section 2.5.1 of [RFC9553] πŸ’œ

ALTID and LANGUAGE convert by the rules in Section 2.3 too. each possible language-dependent alternative becomes an entry of the PatchObject, where the key references the full property 🧚

ADR;TYPE=work;CC=US:
 ;;54321 Oak St;Reston;VA;20190;USA;;;;54321;Oak St;;;;;;
"addresses": {
  "ADDR-1" : {
    "contexts": { "work": true },
    "components": [
      { "kind": "number", "value": "54321" },
      { "kind": "name", "value": "Oak St" },
      { "kind": "locality", "value": "Reston" },
      { "kind": "region", "value": "VA" },
      { "kind": "postcode", "value": "20190" },
      { "kind": "country", "value": "USA" }
    ],
    "countryCode": "US"
  }
}

Figure 15: ADR Conversion Example

for JSCOMPS examples on vCard-structured property values, check Section 3.3.1 🌸


2.7. Communications Properties πŸ’¬

2.7.1. EMAIL πŸ“§

the EMAIL property (Section 6.4.2 of [RFC6350]) converts to an EmailAddress object (Section 2.3.1 of [RFC9553]) in the Card object's emails property (Figure 16). the EmailAddress object's address property is set to the EMAIL value πŸ’Œ

PREF and TYPE convert by the rules in Section 2.3 ✨

EMAIL;TYPE=work:jqpublic@xyz.example.com
EMAIL;PREF=1:jane_doe@example.com
"emails": {
  "EMAIL-1": {
    "contexts": { "work": true },
    "address": "jqpublic@xyz.example.com"
  },
  "EMAIL-2": {
    "address": "jane_doe@example.com",
    "pref": 1
  }
}

Figure 16: EMAIL Conversion Example

2.7.2. IMPP πŸ’¬

the IMPP property (Section 6.4.3 of [RFC6350]) converts to an OnlineService object (Section 2.3.2 of [RFC9553]) in the Card object's onlineServices property (Figure 17). the vCardName property is set to "impp", and the uri property is set to the IMPP value πŸ¦‹

SERVICE-TYPE, USERNAME, PREF, and TYPE convert by the rules in Section 2.3 🫢

IMPP;PREF=1:xmpp:alice@example.com
"onlineServices": {
  "OS-1": {
    "uri": "xmpp:alice@example.com",
    "pref": 1,
    "vCardName": "impp"
  }
}

Figure 17: IMPP Conversion Example

2.7.3. LANG 🌐

the LANG property (Section 6.4.4 of [RFC6350]) converts to a LanguagePref object (Section 2.3.4 of [RFC9553]) in the Card object's preferredLanguages property (Figure 18). the LANG property value converts to the LanguagePref object's language property value πŸ—£οΈ

PREF and TYPE convert by the rules in Section 2.3 πŸ’…

LANG;TYPE=work;PREF=1:en
LANG;TYPE=work;PREF=2:fr
LANG;TYPE=home:fr
"preferredLanguages": {
  "LANG-1": {
    "language": "en",
    "contexts": { "work": true },
    "pref": 1
  },
  "LANG-2": {
    "language": "fr",
    "contexts": { "work": true },
    "pref": 2
  },
  "LANG-3": {
    "language": "fr",
    "contexts": { "private": true }
  }
}

Figure 18: LANG Conversion Example

2.7.4. LANGUAGE πŸ‡©πŸ‡ͺ

the LANGUAGE property (Section 3.3 of [RFC9554]) converts to the Card object's language property (Figure 19) 🌈

LANGUAGE:de-AT
"language": "de-AT"

Figure 19: LANGUAGE Conversion Example

2.7.5. SOCIALPROFILE 🌟

the SOCIALPROFILE property (Section 3.5 of [RFC9554]) converts to an OnlineService object (Section 2.3.2 of [RFC9553]) in the Card object's onlineServices property (Figure 20). the vCardName property is set to "socialprofile", or it can be omitted πŸ™ˆ if the SOCIALPROFILE property value is of type URI, then the OnlineService object's uri property is set. otherwise, the user property is set πŸ“

SERVICE-TYPE, USERNAME, PREF, and TYPE convert by the rules in Section 2.3 πŸ‘‘

SOCIALPROFILE;SERVICE-TYPE=Mastodon:https://example.com/@foo
"onlineServices": {
  ...
  "OS-1": {
    "service": "Mastodon",
    "uri": "https://example.com/@foo"
  }
}

Figure 20: SOCIALPROFILE Conversion Example

2.7.6. TEL πŸ“ž

okay so the TEL property (Section 6.4.1 of [RFC6350]) turns into a Phone object (Section 2.3.3 of [RFC9553]) living in the Card object's phones property (Figure 21) πŸ’–

The TEL-specific values of the TYPE parameter convert to the features property keys, as shown in Table 3 ✨ Now bestie, watch this twist πŸ‘€ Section 6.4.1 of [RFC6350] says the default type is "voice", BUT the default Phone features property is absent by default πŸ’… So an implementation SHOULD only set the Phone object's features property if the TEL property actually has a TEL-specific TYPE parameter set. No phantom features, periodt πŸ™ˆ

                  +=============+===============+
                  | TYPE value  | Phone feature |
                  +=============+===============+
                  | cell        | mobile        |
                  +-------------+---------------+
                  | fax         | fax           |
                  +-------------+---------------+
                  | main-number | main-number   |
                  +-------------+---------------+
                  | pager       | pager         |
                  +-------------+---------------+
                  | text        | text          |
                  +-------------+---------------+
                  | textphone   | textphone     |
                  +-------------+---------------+
                  | video       | video         |
                  +-------------+---------------+
                  | voice       | voice         |
                  +-------------+---------------+

Table 3: TEL TYPE Conversion πŸŽ€

The value of the TEL property converts to the Phone object's number property πŸ“±

The PREF and TYPE parameters convert according to the rules defined in Section 2.3 πŸ¦‹

TEL;VALUE=uri;PREF=1;TYPE="voice,home":tel:+1-555-555-5555;ext=5555
TEL;VALUE=uri;TYPE=home:tel:+33-01-23-45-67
"phones": {
  "PHONE-1": {
    "contexts": { "private": true },
    "features": { "voice": true },
    "number": "tel:+1-555-555-5555;ext=5555",
    "pref": 1
  },
  "PHONE-2": {
    "contexts": { "private": true },
    "number": "tel:+33-01-23-45-67"
  }
}

Figure 21: TEL Conversion Example 🌸

2.8. Geographical Properties 🌍

2.8.1. GEO πŸ—ΊοΈ

The GEO property (Section 6.5.2 of [RFC6350]) converts to the Address object's coordinates property (Section 2.5.1 of [RFC9553]) ✨ Also see Section 2.8.3 to figure out which Address object instance to convert to 🧚

2.8.2. TZ ⏰

The TZ property (Section 6.5.1 of [RFC6350]) converts an Address object (Section 2.5.1 of [RFC9553]) in the Card object's addresses property πŸ’œ

A value of type TEXT converts to the Address object's timeZone property πŸ“

A value of type UTC-OFFSET converts to the Address object's timeZone property if the offset has zero minutes and the hour offset is between -12 and +14, both inclusively. Note that:

  • If the hour offset is zero, use the time zone name "Etc/UTC".
  • Otherwise, construct the time zone name with "Etc/GMT" suffixed with the string representation of the reversed sign hour offset, including the sign but excluding leading zeros and minutes. For example, the UTC offset value "-0500" converts to "Etc/GMT+5".

For such property values, also see Section 2.8.3 to determine which Address object instance to convert to πŸ”

Any other value of type UTC-OFFSET or URI does not convert to an IANA-registered property in JSContact. To convert such property, see Section 2.15.1 πŸ™…β€β™€οΈ

2.8.3. Combining Geographical Properties 🧩

In vCard, the properties ADR, GEO, and TZ occur independently of each other. In JSContact, they all convert to properties of an Address object. It is implementation-specific if these vCard properties convert to separate address instances in JSContact or if some or all of them convert to the same address. That being said, implementations MUST convert the properties to the same address for the following cases:

  • The GROUP parameter values of the properties match.
  • The GROUP parameters are not set, but they are set on any other ADR, GEO, and TZ properties.

2.9. Organizational Properties 🏒

2.9.1. CONTACT-URI πŸ“§

The CONTACT-URI property (Section 2.1 of [RFC8605]) converts to a Link object (Section 2.6.3 of [RFC9553]) in the Card object's links property (Figure 22) πŸ”— The Link object's kind property is set to "contact" and the uri property is set to the CONTACT-URI property value πŸ’Œ

The PREF and TYPE parameters convert according to the rules defined in Section 2.3 πŸŽ€

CONTACT-URI;PREF=1:mailto:contact@example.com
"links": {
  "CONTACT-1": {
    "kind": "contact",
    "uri": "mailto:contact@example.com",
    "pref": 1
  }
}

Figure 22: CONTACT-URI Conversion Example πŸ¦‹

The LOGO property (Section 6.6.3 of [RFC6350]) converts to a Media object (Section 2.6.4 of [RFC9553]) in the Card object's media property (Figure 23) 🌈 The Media object's kind property is set to "logo" and the uri property is set to the LOGO property value 🫢

The PREF and TYPE parameters convert according to the rules defined in Section 2.3 πŸ’…

LOGO:https://www.example.com/pub/logos/abccorp.jpg
"media": {
  "LOGO-1": {
    "kind": "logo",
    "uri": "https://www.example.com/pub/logos/abccorp.jpg"
  }
}

Figure 23: LOGO Conversion Example ✨

2.9.3. MEMBER πŸ‘―

The MEMBER property (Section 6.6.5 of [RFC6350]) converts to the Card object's members property (Figure 24). Each MEMBER property value is a key in the members property. The PREF parameter (Section 5.3 of [RFC6350]) does not convert to JSContact πŸ™ƒ

KIND:group
FN:The Doe family
MEMBER:urn:uuid:03a0e51f-d1aa-4385-8a53-e29025acd8af
MEMBER:urn:uuid:b8767877-b4a1-4c70-9acc-505d3819e519
"kind": "group",
"name": {
  "full": "The Doe family"
},
"uid": "urn:uuid:ab4310aa-fa43-11e9-8f0b-362b9e155667",
"members": {
  "urn:uuid:03a0e51f-d1aa-4385-8a53-e29025acd8af": true,
  "urn:uuid:b8767877-b4a1-4c70-9acc-505d3819e519": true
}

Figure 24: Group Example πŸ‘‘

2.9.4. ORG 🏬

The ORG property (Section 6.6.4 of [RFC6350]) converts to an Organization object (Section 2.2.3 of [RFC9553]) in the Card object's organizations property (Figure 25). The Organization object's name property is set to the ORG property organizational name component. The Organization object's units property is an array of OrgUnit objects that each contain an organizational unit name component value of the ORG property value.

Implementations MAY allow representation of organizational units without the organizational name. In this case, the first component of the ORG value MUST be an empty string (e.g., ORG:;DepartmentA) πŸ§ƒ

The ALTID and LANGUAGE parameters convert according to the rules defined in Section 2.3 🌷

The first item of the comma-separated SORT-AS parameter value converts to the sortAs property of the Organization object. The subsequent items convert to the sortAs property of the corresponding OrgUnit object πŸ—‚οΈ

The TYPE parameter converts according to the rules defined in Section 2.3 🎈

ORG;SORT-AS="ABC":ABC\, Inc.;North American Division;Marketing
"organizations": {
  "ORG-1": {
    "name": "ABC, Inc.",
    "units":[
      { "name": "North American Division" },
      { "name": "Marketing" }
    ],
    "sortAs": "ABC"
  }
}

Figure 25: ORG Conversion Example 🌟

The RELATED property (Section 6.6.6 of [RFC6350]) converts to the Card object's relatedTo property (Figure 26). The property value converts to the key in the relatedTo property. The TYPE parameters convert to the Relation object's relation property (Section 2.1.8 of [RFC9553]). Any other parameters convert as defined in Section 2.15.2 πŸ«‚

RELATED;TYPE=friend:urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
RELATED;TYPE=contact:https://example.com/directory/john.vcf
RELATED;VALUE=text:Please contact my deputy John for any inquiries.
"relatedTo" : {
  "urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6" : {
    "relation" : {
      "friend" : true
    }
  },
  "https://example.com/directory/john.vcf" : {
    "relation" : {
      "contact" : true
    }
  },
  "Please contact my deputy John for any inquiries." : {
    "relation" : { }
  }
}

Figure 26: RELATED Conversion Example πŸ’œ

2.9.6. TITLE and ROLE πŸ’Ό

The TITLE (Section 6.6.1 of [RFC6350]) and ROLE (Section 6.6.2 of [RFC6350]) properties convert to a Title object (Section 2.2.5 of [RFC9553]) in the Card object's titles property (Figure 27) πŸ‘©β€πŸ’Ό The Title object's kind property is set to "title" or "role" for the TITLE and ROLE vCard properties, respectively. The name property is set to the vCard property value.

The value of the organizationId property can be derived if the TITLE or ROLE property is a member of a vCard property group and if exactly one other ORG property is also a part of that group πŸ”Ž

The ALTID and LANGUAGE parameters convert according to the rules defined in Section 2.3 🌼

TITLE:Research Scientist
group1.ROLE:Project Leader
group1.ORG:ABC, Inc.
"titles": {
  "TITLE-1": {
    "kind": "title",
    "name": "Research Scientist"
  },
  "TITLE-2": {
    "kind": "role",
    "name": "Project Leader",
    "organizationId": "ORG-1"
  }
},
"organizations": {
  "ORG-1": {
    "name": "ABC, Inc."
  }
}

Figure 27: TITLE and ROLE Conversion Example πŸ†

2.10. Personal Information Properties 🧠

2.10.1. EXPERTISE πŸŽ“

The EXPERTISE property (Section 2.1 of [RFC6715]) converts to a PersonalInfo object (Section 2.8.4 of [RFC9553]) in the Card object's personalInfo property (Figure 28). The PersonalInfo object's kind property is set to "expertise" 🌟

The INDEX and LEVEL parameters convert according to the rules defined in Section 2.3 🍭

EXPERTISE;LEVEL=beginner;INDEX=2:Chinese literature
EXPERTISE;INDEX=1;LEVEL=expert:chemistry
"personalInfo": {
  "PERSINFO-1" : {
    "kind": "expertise",
    "value": "Chinese literature",
     "level": "low",
     "listAs": 2
  },
  "PERSINFO-2" : {
    "kind": "expertise",
    "value": "chemistry",
    "level": "high",
    "listAs": 1
  }
}

Figure 28: EXPERTISE Conversion Example 🧁

2.10.2. HOBBY 🎨

The HOBBY property (Section 2.2 of [RFC6715]) converts to a PersonalInfo object (Section 2.8.4 of [RFC9553]) in the Card object's personalInfo property (Figure 29). The PersonalInfo object's kind property is set to "hobby" 🧡

The INDEX and LEVEL parameters convert according to the rules defined in Section 2.3 🌈

HOBBY;INDEX=1;LEVEL=high:reading
HOBBY;INDEX=2;LEVEL=high:sewing
"personalInfo": {
  "PERSINFO-1" : {
    "kind": "hobby",
    "value": "reading",
    "level": "high",
    "listAs": 1
  },
  "PERSINFO-2" : {
    "kind": "hobby",
    "value": "sewing",
    "level": "high",
    "listAs": 2
  }
}

Figure 29: HOBBY Conversion Example 🌸

2.10.3. INTEREST πŸŽ€

okay so the INTEREST property (Section 2.3 of [RFC6715]) turns into a PersonalInfo object (Section 2.8.4 of [RFC9553]) that lives in the Card object's personalInfo property (Figure 30) πŸ’… the PersonalInfo object's kind gets set to "interest" ✨

the INDEX and LEVEL parameters convert according to the rules defined in Section 2.3 🫢

INTEREST;INDEX=1;LEVEL=medium:r&b music
INTEREST;INDEX=2;LEVEL=high:rock&roll music
"personalInfo": {
  "PERSINFO-1" : {
    "kind": "interest",
    "value": "r&b music",
    "level": "medium",
    "listAs": 1
  },
  "PERSINFO-2" : {
    "kind": "interest",
    "value": "rock&roll music",
    "level": "high",
    "listAs": 2
  }
}

Figure 30: INTEREST Conversion Example

2.10.4. ORG-DIRECTORY πŸ—‚οΈ

the ORG-DIRECTORY property (Section 2.4 of [RFC6715]) [RFC6715] becomes a Directory object (Section 2.6.2 of [RFC9553]) in the Card object's directories property (Figure 31) 🌸 the Directory object's kind is set to "directory", and the uri property is set to the ORG-DIRECTORY property value πŸ’–

the INDEX, PREF, and TYPE parameters convert according to the rules defined in Section 2.3 ✨

ORG-DIRECTORY;INDEX=1:https://directory.mycompany.example.com
ORG-DIRECTORY;PREF=1:ldap://ldap.tech.example/o=Tech,ou=Engineering
"directories": {
  "DIRECTORY-1": {
    "kind": "directory",
    "uri": "https://directory.mycompany.example.com",
    "listAs": 1
  },
  "DIRECTORY-2": {
    "kind": "directory",
    "uri": "ldap://ldap.tech.example/o=Tech,ou=Engineering",
    "pref": 1
  }
}

Figure 31: ORG-DIRECTORY Conversion Example

2.11. Explanatory Properties 🌈

2.11.1. CATEGORIES 🏷️

the CATEGORIES property (Section 6.7.1 of [RFC6350]) converts to a set of entries in the Card object's keywords property (Figure 32) πŸ“ the keys are the comma-separated text values of the CATEGORIES property πŸ’…

in this case the PREF parameter doesn't have a JSContact counterpart, but the implementors MAY insert the entries by order of preference ✨

CATEGORIES:internet,IETF,Industry,Information Technology
"keywords": {
  "internet": true,
  "IETF": true,
  "Industry": true,
  "Information Technology": true
}

Figure 32: CATEGORIES Conversion Example

2.11.2. CLIENTPIDMAP 🧩

the CLIENTPIDMAP property (Section 6.7.7 of [RFC6350]) converts to the vCardProps (Section 2.15.1) property 🫧

2.11.3. CREATED πŸ•°οΈ

the CREATED property (Section 3.1 of [RFC9554]) converts to the Card object's created property (Figure 33) 🌷

CREATED:19940930T143510Z
"created": "1994-09-30T14:35:10Z"

Figure 33: CREATED Conversion Example

2.11.4. NOTE πŸ“

the NOTE property (Section 6.7.2 of [RFC6350]) converts to a Note object (Section 2.8.3 of [RFC9553]) in the Card object's notes property (Figure 34) πŸ’Œ

the ALTID and LANGUAGE parameters convert according to the rules defined in Section 2.3 🫢

NOTE;CREATED=20221123T150132Z;AUTHOR-NAME="John":
  Office hours are from 0800 to 1715 EST\, Mon-Fri.
"notes": {
  "NOTE-1" : {
     "note": "Office hours are from 0800 to 1715 EST, Mon-Fri.",
     "created": "2022-11-23T15:01:32Z",
     "author": {
       "name": "John"
     }
  }
}

Figure 34: NOTE Conversion Example

2.11.5. PRODID πŸ–₯️

the PRODID property (Section 6.7.3 of [RFC6350]) converts to the Card object's prodId property (Figure 35) πŸ’œ

PRODID:ACME Contacts App version 1.23.5
"prodId": "ACME Contacts App version 1.23.5"

Figure 35: PRODID Conversion Example

2.11.6. REV ⏰

the REV property (Section 6.7.4 of [RFC6350]) converts to the Card object's updated property (Figure 36) πŸ¦‹

REV:19951031T222710Z
"updated": "1995-10-31T22:27:10Z"

Figure 36: REV Conversion Example

2.11.7. SOUND πŸ”Š

the SOUND property (Section 6.7.5 of [RFC6350]) converts to a Media object (Section 2.6.4 of [RFC9553]) in the Card object's media property (Figure 37) 🎧 the Media object's kind is set to "sound", and the uri property is set to the SOUND value 🎢

the PREF and TYPE parameters convert according to the rules defined in Section 2.3 ✨

SOUND:CID:JOHNQPUBLIC.19960229T080000.xyzMail@example.com
"media": {
  ...
  "SOUND-1": {
    "kind": "sound",
    "uri": "CID:JOHNQPUBLIC.19960229T080000.xyzMail@example.com"
  }
}

Figure 37: SOUND Conversion Example

2.11.8. UID πŸ†”

the UID property (Section 6.7.6 of [RFC6350]) converts to the Card object's uid property (Figure 38) πŸͺͺ

UID:urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
"uid": "urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6"

Figure 38: UID Conversion Example

2.11.9. URL πŸ”—

the URL property (Section 6.7.8 of [RFC6350]) converts to a Link object (Section 2.6.3 of [RFC9553]) in the Card object's links property (Figure 39) 🌐 the Link object's uri property is set to the URL value πŸ’…

the PREF and TYPE parameters convert according to the rules defined in Section 2.3 🫢

URL:https://example.org/restaurant.french/~chezchic.html
"links": {
  "LINK-1": {
    "uri": "https://example.org/restaurant.french/~chezchic.html"
  }
}

Figure 39: URL Conversion Example

2.11.10. VERSION πŸ”’

the VERSION property (Section 6.7.9 of [RFC6350]) converts to the vCardProps (Section 2.15.1) property 🧚

2.11.11. X-ABLabel 🏷️

the X-ABLabel property is experimental, but it's widely used in existing vCard data, so it's giving real-world relevance πŸ™ˆ it converts to the label property of a JSContact object. the X-ABLabel property is preceded by a vCard property group name, and the label converts to the JSContact object that was converted from a vCard property of the same group 🫧

the group name is not preserved, and implementations are free to choose any unique group name when converting back to vCard 🌈 for an example on how to preserve the group name, see Section 2.3.9 πŸ’–

item1.TEL;VALUE=uri:tel:+1-555-555-5555
item1.X-ABLabel:foo
"phones": {
  "p1": {
    "number": "tel:+1-555-555-5555",
    "label": "foo"
  }
}

Figure 40: X-ABLabel Conversion Example

2.12. Security Properties πŸ”

2.12.1. KEY πŸ—οΈ

the KEY property (Section 6.8.1 of [RFC6350]) converts to a CryptoKey object (Section 2.6.1 of [RFC9553]) in the Card object's cryptoKeys property (Figure 41) πŸ”‘ the CryptoKey object's uri property is set to the KEY property value πŸ’œ

the PREF and TYPE parameters convert according to the rules defined in Section 2.3 ✨

KEY:https://www.example.com/keys/jdoe.cer
"cryptoKeys": {
  "KEY-1": {
    "uri": "https://www.example.com/keys/jdoe.cer"
  }
}

Figure 41: KEY Conversion Example

2.13. Calendar Properties πŸ“…

2.13.1. CALADRURI πŸ“‡

the CALADRURI property (Section 6.9.2 of [RFC6350]) converts to a SchedulingAddress object (Section 2.4.2 of [RFC9553]) in the Card object's schedulingAddresses property (Figure 42) πŸ—“οΈ the SchedulingAddress object's uri property is set to the CALADRURI value πŸ’…

the PREF parameter (Section 5.3 of [RFC6350]) converts according to the rules defined in Section 2.3 🫢

CALADRURI;PREF=1:mailto:janedoe@example.com
CALADRURI:https://example.com/calendar/jdoe
"schedulingAddresses": {
  "SCHEDULING-1": {
    "uri": "mailto:janedoe@example.com",
    "pref": 1
  },
  "SCHEDULING-2": {
    "uri": "https://example.com/calendar/jdoe"
  }
}

Figure 42: CALADRURI Conversion Example

2.13.2. CALURI πŸ—“οΈ

the CALURI property (Section 6.9.3 of [RFC6350]) converts to a Calendar object (Section 2.4.1 of [RFC9553]) in the Card object's calendars property (Figure 43) 🌸 the Calendar object's kind is set to "calendar", and the uri property is set to the CALURI value ✨

the PREF and TYPE parameters convert according to the rules defined in Section 2.3 πŸ’–

CALURI;PREF=1:https://cal.example.com/calA
CALURI;MEDIATYPE=text/calendar:https://ftp.example.com/calA.ics
"calendars": {
  "CAL-1": {
    "kind": "calendar",
    "uri": "https://cal.example.com/calA",
    "pref": 1
  },
  "CAL-2": {
    "kind": "calendar",
    "uri": "https://ftp.example.com/calA.ics",
    "mediaType": "text/calendar"
  }
}

Figure 43: CALURI Conversion Example

2.13.3. FBURL 🫧

the FBURL property (Section 6.9.1 of [RFC6350]) converts to a Calendar object (Section 2.4.1 of [RFC9553]) in the Card object's calendars property (Figure 44) πŸ¦‹ the Calendar object's kind is set to "freeBusy", and the uri property is set to the FBURL value πŸ’…

the PREF and TYPE parameters convert according to the rules defined in Section 2.3 🫢

FBURL;PREF=1:https://www.example.com/busy/janedoe
FBURL;MEDIATYPE=text/calendar:https://example.com/busy/project-a.ifb
"calendars": {
  "FBURL-1": {
    "kind": "freeBusy",
    "uri": "https://www.example.com/busy/janedoe",
    "pref": 1
  },
  "FBURL-2": {
    "kind": "freeBusy",
    "uri": "https://example.com/busy/project-a.ifb",
    "mediaType": "text/calendar"
  }
}

Figure 44: FBURL Conversion Example

2.14. Extended Properties and Parameters πŸ¦‹

extended properties and parameters convert as specified in Section 2.15 🧚

2.15. New JSContact Properties 🧚

okay so vCards may contain properties or parameters for which no IANA-registered JSContact property is defined πŸ‘€ for example, a vCard may contain properties and parameters whose semantics or purposes the implementation doesn't know, see Section 6.10 of [RFC6350] πŸ’€

this section defines JSContact properties by which such vCard properties and parameters MAY be represented in JSContact πŸ’œ implementations MAY choose to convert differently if they deem that more appropriate 🫢

2.15.1. vCardProps 🫧

vCardProps: JCardProp[] (optional). contains vCard properties that get set in the vCard represented by this JSContact object πŸ’… the JCardProp type denotes a jCard-encoded vCard property as defined in Section 3.3 of [RFC7095] ✨

Example: This illustrates how to convert a vCard extension property:

item1.X-FOO;X-BAR=Hello:World!
"vCardProps": [
  ["x-foo", {
    "x-bar": "Hello",
    "group": "item1"
  }, "unknown", "World!"]
]

Figure 45: JSContact vCardProps Example

2.15.2. vCardParams 🌈

vCardParams: String[String|String[]] (optional). contains vCard parameters that are set on the vCard property represented by this JSContact object πŸŽ€ the value MUST be a JSON object containing vCard property parameters as defined in Section 3.3 of [RFC7095] 🫢 each entry represents a parameter of the vCard property that converts to the JSContact object πŸ’–

Example: This illustrates how to convert a vCard extension parameter:

EMAIL;X-FOO=Bar:jane_doe@example.com
"emails": {
  "email1": {
    "address": "jane_doe@example.com",
    "vCardParams": {
      "x-foo": "Bar"
    }
  }
}

Figure 46: JSContact vCardParams Example

2.15.3. vCardName πŸ’–

vCardName: String (optional). okay so this one holds the name of the vCard element that this JSContact object represents πŸŽ€ Why does that matter? When multiple vCard properties all convert to the same JSContact type, this is how you keep track of which one it started as 🧚 The case-insensitive value MUST be valid according to the "name" ABNF defined in Section 3.3 of [RFC6350]. πŸ’…

Example: Both vCard IMPP and SOCIALPROFILE convert to an OnlineService object (Section 2.3.2 of [RFC9553]) in JSContact. The vCardName property value shows that the vCard source element was IMPP, like this πŸ‘€

IMPP:xmpp:alice@example.com
"onlineServices": {
  "os1": {
    "uri": "xmpp:alice@example.com",
    "vCardName": "impp"
  },
}

Figure 47: JSContact vCardName Example


3. Converting JSContact to vCard πŸ¦‹

3.1. Conversion Rules

So a Card object goes back to vCard by running the reverse of the vCard-to-JSContact rules πŸ”„ On top of the ones in Appendix A, these also apply:

  • Multivalued JSContact properties turn into separate copies of their equivalent vCard property, and every PROP-ID parameter MUST be set to the Id-typed key of the converted value (see Section 2.3.18).
  • The full property of the name property in JSContact is optional, but the FN property is mandatory in vCard. Here's how that plays out:
    • If the Name object's full property is set, then implementations MUST use its value for the vCard FN property.
    • If the Name object's full property is not set, then implementations SHOULD derive the full name from the Name object's components property values. If the isOrdered property is "true", then this can be done by concatenating the name component values. Otherwise, or as an alternative, an implementation can choose any other heuristic to generate the full name from its components, such as [CLDRPersonName]. Implementations MUST set the DERIVED parameter on the FN property. ✨
    • Otherwise, the FN property MUST be set to the empty value.
  • Vendor-specific and unknown properties convert to vCard as outlined in Section 3.1.1.

3.1.1. Converting Unknown Properties

JSContact objects can have properties that no IANA-registered vCard property covers πŸ€·β€β™€οΈ Like, a JSContact object might hold vendor-specific stuff where nobody knows what it means or what it's for πŸ‘€

This spec introduces the JSPROP vCard property (Section 3.2.1) and the JSPTR vCard parameter (Section 3.3.2), and that's how those JSContact properties MAY get represented in vCard 🌈 Implementations MAY choose to convert differently if they deem that more appropriate. 🫢

3.2. New vCard Properties

3.2.1. JSPROP

Property name: JSPROP

Purpose: Represents a JSContact property in vCard.

Value type: TEXT. Also peek at "Format definition" below for the value restrictions πŸ‘€

Conformance: Can be specified multiple times in a vCard.

Property parameters: The JSPTR parameter MUST be set on this property. Other IANA-registered and experimental property parameters can be specified on it too.

Description: This one converts any arbitrary JSContact property to and from vCard πŸ” The vCard property value is the JSON-encoded value of that JSContact property, stored as a TEXT value. The JSON format MUST be compact, e.g., no insignificant whitespace (as defined in Section 2 of [RFC8259]) πŸ§ƒ The JSPTR parameter's value points at the JSContact property inside the Card.

The root of the JSON pointer is always the Card object this vCard converts to 🌸, whether or not the pointer starts with the SOLIDUS (U+002F) character. The pointer MUST NOT reference into an array.

All the JSPROP properties in one vCard team up to form a PatchObject (as defined in [RFC9553]) 🧩 Each JSPTR value lines up with a key in that PatchObject, and the JSPROP value is the value for that key. Going from vCard to JSContact, the PatchObject MUST only be applied after every other vCard property has already been converted. The PatchObject MUST be valid too, and an invalid PatchObject MUST NOT be applied. 🚫

Format definition: Here's the notation this property is defined with πŸ“

jsprop = "JSPROP" jsprop-param ":" TEXT

jsprop-param  = *(
            ; The following are REQUIRED and MUST NOT
            ; occur more than once
            ( ";" jsptr-param ) /    ; see next section
            ( ";" "VALUE" "=" "TEXT")
            ;
            ; The following is OPTIONAL
            ; and MAY occur more than once.
            ;
            (";" other-param)
            ;
            )

Example(s): Here's how to convert a property sitting at the top level of a Card that the implementation doesn't recognize πŸ‘€

"someUnknownProperty": true
JSPROP;JSPTR="someUnknownProperty":true

Figure 48: Unknown Property Example

Next up: a vendor-specific property at the top level of a Card πŸ’… Heads up, the JSPTR value has to be a quoted string, which lets the path include the COLON (U+003A) character πŸŽ€

"example.com:foo": {
  "bar": 1234
}
JSPROP;JSPTR="example.com:foo":{"bar":1234}

Figure 49: Vendor-Specific Property Conversion Example

Last one: a vendor-specific property nested down a level, using a path relative to the Card. It's not recommended, but this property name has a SOLIDUS (U+002F) in it, so it needs escaping in the JSON pointer πŸ™ˆ

"phones": {
  "phone1": {
    "number": "tel:+33-01-23-45-67",
    "example.com:foo/bar": "tux hux"
  }
}
TEL:tel:+33-01-23-45-67
JSPROP;JSPTR="phones/phone1/example.com:foo~1bar":
 "tux hux"

Figure 50: Nested Vendor-Specific Property Example with a Path Relative to Card


3.3. New vCard Parameters ✨

3.3.1. JSCOMPS πŸŽ€

Parameter name: JSCOMPS

Purpose: okay bestie, this parameter decides the order and separators for the pieces of a structured property value πŸ’…

Description: the JSCOMPS parameter is the translator for name and address components between JSContact and vCard ✨ It keeps the order of the JSContact property's components and carries the verbatim values of the separator components πŸ¦‹

If this parameter is set and its value is valid (see later), then implementations MUST set the isOrdered property of the Name or Address object to "true". Otherwise, they MUST set the isOrdered property value to "false" 🫢

The JSCOMPS parameter value is a structured type value, and its value MUST be quoted πŸ’– It's a sequence of entries separated by the SEMICOLON character (U+003B). The first entry sets the value of the defaultSeparator property. If that entry is the empty string, then no default separator is defined. Otherwise, the first entry MUST be a separator entry 🌸 All the following entries, processed in order, make an ordered list of JSContact components, and each one MUST be one of these two kinds:

  1. A positional. This points at a component value in the vCard structured value. A position is the numeric index of a component in the structured value, optionally followed by a COMMA (U+002C) character and the non-zero index of a value within that component. The zero index selects the first component or value, respectively. The second index is zero by default, in which case it MUST be omitted (as well as the leading COMMA) 🧚

The resulting JSContact component gets its kind from its position in the vCard structured value, and its value is the verbatim value of the vCard component. Figures 51 and 52 show this by example ✨

  1. A separator. This contains the verbatim value of a separator component. It starts with the LATIN SMALL LETTER S (U+0073) character, then the COMMA (U+002C) character, then zero or more "param-value" characters (see Section 3.3 of [RFC6350]). The COMMA (U+002C) and SEMICOLON (U+003B) characters MUST be escaped according to the rules defined in Section 3.4 of [RFC6350]. Figure 53 shows this by example πŸ’œ

The resulting JSContact component gets its kind set to "separator", and its value is the verbatim value of the entry.

A JSCOMPS parameter value is valid if and only if:

  • All indexes in the positional entries refer to an existing component value in the vCard property value.
  • The count of positional entries equals the count of deduplicated component values. Deduplication is required because some values may show up in both their designated and backwards-compatible components in the vCard property value πŸ‘‘
    • A value that occurs in both the N property secondary surname component and the family name component only counts once.
    • A value that occurs in both the N property generation component and the honorific suffix component only counts once.
    • A value in the ADR property street address component does not count if the ADR property value contains a value in one of the new components defined in [RFC9554].
    • All other values count once each.

Format definition:

jscomps-param      = "JSCOMPS" "=" DQUOTE [jscomps-entry-sep ] ";"
                                   jscomps-entrylist DQUOTE

jscomps-entrylist  = jscomps-entry *(";" jscomps-entry)
jscomps-entry      = jscomps-entry-pos / jscomps-entry-sep
jscomps-entry-pos  = 1*DIGIT [ "," 1*DIGIT ]
jscomps-entry-sep  = "s" "," jscomps-entry-verb
jscomps-entry-verb = *QSAFE-CHAR ; encode according to RFC 6868

Example(s): this one's the "Jane Doe" example, and it's giving clean positional entries πŸ“ The given name comes before the surname. No secondary index is needed for either positional, because both are zero.

"name": {
  "components": [
    { "kind": "given", "value": "Jane" },
    { "kind": "surname", "value": "Doe" }
  ],
  "isOrdered": true
}
N;JSCOMPS=";1;0":Doe;Jane;;;;;;
FN;DERIVED=TRUE:Jane Doe

Figure 51: Example of a Secondary Positional Index

Now the secondary positional index, and it's so iconic πŸ™ˆ The "Jr." generation marker only counts once, because it shows up in both the designated generation component and the backwards-compatible honorific suffixes component.

"name": {
  "components": [
    { "kind": "given", "value": "John" },
    { "kind": "given2", "value": "Philip" },
    { "kind": "given2", "value": "Paul" },
    { "kind": "surname", "value": "Stevenson" },
    { "kind": "generation", "value": "Jr." },
    { "kind": "credential", "value": "M.D." }
  ],
  "isOrdered": true
}
N;JSCOMPS=";1;2;2,1;0;6;4,1":
 Stevenson;John;Philip,Paul;;Jr.,M.D.;;Jr.

Figure 52: Example of Positional Entries

Last one, and it's a whole vibe πŸ¦‹ This shows separator entries for the (shortened for brevity) address "54321 Oak St, Reston". The first entry sets the default separator to ", ". The second and fourth positional entries are separated with the separator value " ". For backwards compatibility, the street address component of the ADR property contains both the street number and name, but it isn't referred to in the JSCOMPS parameter, so it doesn't contribute to the count of values.

"addresses": {
  "a1": {
    "components": [
      { "kind": "number", "value": "54321" },
      { "kind": "separator", "value": " " },
      { "kind": "name", "value": "Oak St" },
      { "kind": "locality", "value": "Reston" }
    ],
    "defaultSeparator": ", ",
    "isOrdered": true
  }
}
ADR;JSCOMPS="s,\, ;11;s, ;10;3":
 ;;54321 Oak St;Reston;;;;;;;Oak St;54321;;;;;;

Figure 53: Example of Separator Entries


3.3.2. JSPTR 🌈

Parameter name: JSPTR

Purpose: this parameter gets set on a JSPROP (Section 3.2.1) property πŸ’… Its value is a JSON pointer [RFC6901] that points to the JSContact property holding the value of the JSPROP property.

Description: this parameter has a single value, and that value MUST be a valid JSON pointer as defined in [RFC6901]. Note that the value MUST be quoted according to the "param-value" ABNF in [RFC6350] πŸŽ€

Format definition:

jsptr-param  = "JSPTR" "=" param-value
             ; also see param-value in RFC 6350, Section 3.3

Example(s): here's a simple one, and for more examples, check out Section 3.2.1 🫢

JSPROP;JSPTR="example.com:foo":"bar"

4. Security Considerations πŸ”’

This specification defines how to convert between the JSContact and vCard formats. The security considerations for parsing and formatting such data apply, and they're outlined in Section 4 of [RFC9553] and Section 9 of [RFC6350]. Please take these seriously, bestie, this is not the place for vibes-only security 😭

5. IANA Considerations 🌸

5.1. New vCard Property

IANA has added the following entry to the "vCard Properties" registry, as defined in Section 10.3.1 of [RFC6350] ✨

+===========+==========+=========================+
| Namespace | Property | Reference               |
+===========+==========+=========================+
|           | JSPROP   | RFC 9555, Section 3.2.1 |
+-----------+----------+-------------------------+

Table 4: New vCard Property

5.2. New vCard Parameter

IANA has added the following entry to the "vCard Parameters" registry, as defined in Section 10.3.2 of [RFC6350] πŸ¦‹

+===========+===========+=========================+
| Namespace | Parameter | Reference               |
+===========+===========+=========================+
|           | JSPTR     | RFC 9555, Section 3.3.2 |
+-----------+-----------+-------------------------+

Table 5: New vCard Parameter

5.3. New JSContact Properties

IANA has added the following entries to the "JSContact Properties" registry. Note that the Since Version is 1.0, the Until Version is not set, and the Change Controller is IETF for all of these properties πŸ’œ

+===========+=======================+=========+========+===========+
|Property   |Property Type          |Property |Intended|Reference/ |
|Name       |                       |Context  |Usage   |Description|
+===========+=======================+=========+========+===========+
|vCardName  |String                 |Any      |common  |RFC 9555,  |
|           |                       |JSContact|        |Section    |
|           |                       |object   |        |2.15.3     |
+-----------+-----------------------+---------+--------+-----------+
|vCardParams|String[String|String[]]|Any      |common  |RFC 9555,  |
|           |                       |JSContact|        |Section    |
|           |                       |object   |        |2.15.2     |
+-----------+-----------------------+---------+--------+-----------+
|vCardProps |JCardProp[]            |Card     |common  |RFC 9555,  |
|           |                       |         |        |Section    |
|           |                       |         |        |2.15.1     |
+-----------+-----------------------+---------+--------+-----------+

Table 6: JSContact Properties Registry

5.4. New JSContact Type

IANA has added the following entry to the "JSContact Types" registry. Note that the Since Version is 1.0, the Until Version is not set, and the Change Controller is IETF for this type πŸ“

+===========+================+==========================+
| Type Name | Intended Usage | Reference/Description    |
+===========+================+==========================+
| JCardProp | common         | RFC 9555, Section 2.15.1 |
+-----------+----------------+--------------------------+

Table 7: JSContact Types Registry

6. References ✨

6.1. Normative References πŸ“šβœ¨

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC5646] Phillips, A., Ed. and M. Davis, Ed., "Tags for Identifying Languages", BCP 47, RFC 5646, DOI 10.17487/RFC5646, September 2009, <https://www.rfc-editor.org/info/rfc5646>.

[RFC6350] Perreault, S., "vCard Format Specification", RFC 6350, DOI 10.17487/RFC6350, August 2011, <https://www.rfc-editor.org/info/rfc6350>.

[RFC6473] Saint-Andre, P., "vCard KIND:application", RFC 6473, DOI 10.17487/RFC6473, December 2011, <https://www.rfc-editor.org/info/rfc6473>.

[RFC6474] Li, K. and B. Leiba, "vCard Format Extensions: Place of Birth, Place and Date of Death", RFC 6474, DOI 10.17487/RFC6474, December 2011, <https://www.rfc-editor.org/info/rfc6474>.

[RFC6715] Cauchie, D., Leiba, B., and K. Li, "vCard Format Extensions: Representing vCard Extensions Defined by the Open Mobile Alliance (OMA) Converged Address Book (CAB) Group", RFC 6715, DOI 10.17487/RFC6715, August 2012, <https://www.rfc-editor.org/info/rfc6715>.

[RFC6869] Salgueiro, G., Clarke, J., and P. Saint-Andre, "vCard KIND:device", RFC 6869, DOI 10.17487/RFC6869, February 2013, <https://www.rfc-editor.org/info/rfc6869>.

[RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., "JavaScript Object Notation (JSON) Pointer", RFC 6901, DOI 10.17487/RFC6901, April 2013, <https://www.rfc-editor.org/info/rfc6901>.

[RFC7095] Kewisch, P., "jCard: The JSON Format for vCard", RFC 7095, DOI 10.17487/RFC7095, January 2014, <https://www.rfc-editor.org/info/rfc7095>.

[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, <https://www.rfc-editor.org/info/rfc8259>.

[RFC9553] Stepanek, R. and M. Loffredo, "JSContact: A JSON Representation of Contact Data", RFC 9553, DOI 10.17487/RFC9553, May 2024, <https://www.rfc-editor.org/info/rfc9553>.

[RFC9554] Stepanek, R. and M. Loffredo, "vCard Format Extensions for JSContact", RFC 9554, DOI 10.17487/RFC9554, May 2024, <https://www.rfc-editor.org/info/rfc9554>.


6.2. Informative References 🌸

[CLDRPersonName] Davis, M., Edberg, P., Gillam, R., Kolisnychenko, A., McKenna, M., and other CLDR committee members, "Unicode Locale Data Markup Language (LDML) Part 8: Person Names", Unicode Technical Standard #35, Version 44.1, July 2023, <https://www.unicode.org/reports/tr35/tr35-personNames.html>.

[RFC8605] Hollenbeck, S. and R. Carney, "vCard Format Extensions: ICANN Extensions for the Registration Data Access Protocol (RDAP)", RFC 8605, DOI 10.17487/RFC8605, May 2019, <https://www.rfc-editor.org/info/rfc8605>.

[vOBJECT] Tse, R., Tam, P., and M. Douglass, "vObject Internationalization", Work in Progress, Internet-Draft, draft-calconnect-vobject-i18n-00, 8 June 2018, <https://datatracker.ietf.org/doc/html/draft-calconnect-vobject-i18n-00>.


Appendix A. Reverse Rules of Converting a vCard to a JSContact Card πŸ¦‹

Table 8 lists the relevant document sections for each JSContact type and property. πŸ’–

Okay bestie, this is the lookup table πŸ’– It's basically a cheat sheet that tells you where every JSContact type and property gets explained. Find your type, find your property, and the Relevant Section(s) column tells you where to look πŸ¦‹

     +===================+=====================+=====================+
     | JSContact Type    | Property Name       | Relevant Section(s) |
     +===================+=====================+=====================+
     | Address           | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Address           | components          | Sections 2.6.1 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Address           | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Address           | coordinates         | Sections 2.3.8 and  |
     |                   |                     | 2.8.1               |
     +-------------------+---------------------+---------------------+
     | Address           | country             | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | countryCode         | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | defaultSeparator    | Sections 2.6.1 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Address           | full                | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | isOrdered           | Sections 2.6.1 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Address           | locality            | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | phoneticScript      | Sections 2.3.15 and |
     |                   |                     | 2.3.19              |
     +-------------------+---------------------+---------------------+
     | Address           | phoneticSystem      | Section 2.3.15      |
     +-------------------+---------------------+---------------------+
     | Address           | postcode            | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Address           | region              | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Address           | timeZone            | Sections 2.3.23 and |
     |                   |                     | 2.8.2               |
     +-------------------+---------------------+---------------------+
     | AddressComponent  | phonetic            | Section 2.3.15      |
     +-------------------+---------------------+---------------------+
     | Anniversary       | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Anniversary       | date                | Section 2.5.1       |
     +-------------------+---------------------+---------------------+
     | Anniversary       | kind                | Section 2.5.1       |
     +-------------------+---------------------+---------------------+
     | Anniversary       | place               | Section 2.5.1       |
     +-------------------+---------------------+---------------------+
     | Author            | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Author            | name                | Section 2.3.3       |
     +-------------------+---------------------+---------------------+
     | Author            | uri                 | Section 2.3.2       |
     +-------------------+---------------------+---------------------+
     | Calendar          | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Calendar          | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Calendar          | kind                | Sections 2.13.2 and |
     |                   |                     | 2.13.3              |
     +-------------------+---------------------+---------------------+
     | Calendar          | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | Calendar          | mediaType           | Section 2.3.14      |
     +-------------------+---------------------+---------------------+
     | Calendar          | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Calendar          | uri                 | Sections 2.13.2 and |
     |                   |                     | 2.13.3              |
     +-------------------+---------------------+---------------------+
     | Card              | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Card              | @version            | not applicable      |
     +-------------------+---------------------+---------------------+
     | Card              | addresses           | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Card              | anniversaries       | Section 2.5.1       |
     +-------------------+---------------------+---------------------+
     | Card              | calendars           | Sections 2.13.2 and |
     |                   |                     | 2.13.3              |
     +-------------------+---------------------+---------------------+
     | Card              | created             | Section 2.11.3      |
     +-------------------+---------------------+---------------------+
     | Card              | directories         | Sections 2.4.3 and  |
     |                   |                     | 2.10.4              |
     +-------------------+---------------------+---------------------+
     | Card              | emails              | Section 2.7.1       |
     +-------------------+---------------------+---------------------+
     | Card              | keywords            | Section 2.11.1      |
     +-------------------+---------------------+---------------------+
     | Card              | kind                | Section 2.4.2       |
     +-------------------+---------------------+---------------------+
     | Card              | language            | Section 2.7.4       |
     +-------------------+---------------------+---------------------+
     | Card              | links               | Sections 2.9.1 and  |
     |                   |                     | 2.11.9              |
     +-------------------+---------------------+---------------------+
     | Card              | localizations       | Section 2.3.11      |
     +-------------------+---------------------+---------------------+
     | Card              | media               | Sections 2.5.7,     |
     |                   |                     | 2.9.2, and 2.11.7   |
     +-------------------+---------------------+---------------------+
     | Card              | members             | Section 2.9.3       |
     +-------------------+---------------------+---------------------+
     | Card              | name                | Section 2.5.5       |
     +-------------------+---------------------+---------------------+
     | Card              | nicknames           | Section 2.5.6       |
     +-------------------+---------------------+---------------------+
     | Card              | notes               | Section 2.11.4      |
     +-------------------+---------------------+---------------------+
     | Card              | onlineServices      | Section 2.7.2       |
     +-------------------+---------------------+---------------------+
     | Card              | organizations       | Section 2.9.4       |
     +-------------------+---------------------+---------------------+
     | Card              | personalInfo        | Sections 2.10.1,    |
     |                   |                     | 2.10.2, and 2.10.3  |
     +-------------------+---------------------+---------------------+
     | Card              | phones              | Section 2.7.6       |
     +-------------------+---------------------+---------------------+
     | Card              | preferredLanguages  | Section 2.7.3       |
     +-------------------+---------------------+---------------------+
     | Card              | prodId              | Section 2.11.5      |
     +-------------------+---------------------+---------------------+
     | Card              | relatedTo           | Section 2.9.5       |
     +-------------------+---------------------+---------------------+
     | Card              | schedulingAddresses | Section 2.13.1      |
     +-------------------+---------------------+---------------------+
     | Card              | speakToAs           | Section 2.5.4       |
     +-------------------+---------------------+---------------------+
     | Card              | titles              | Section 2.9.6       |
     +-------------------+---------------------+---------------------+
     | Card              | uid                 | Section 2.11.8      |
     +-------------------+---------------------+---------------------+
     | Card              | updated             | Section 2.11.6      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | kind                | not applicable      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | mediaType           | Section 2.3.14      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | CryptoKey         | uri                 | Section 2.12.1      |
     +-------------------+---------------------+---------------------+
     | Directory         | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Directory         | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Directory         | kind                | Sections 2.4.3 and  |
     |                   |                     | 2.10.4              |
     +-------------------+---------------------+---------------------+
     | Directory         | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | Directory         | listAs              | Section 2.3.10      |
     +-------------------+---------------------+---------------------+
     | Directory         | mediaType           | Section 2.3.14      |
     +-------------------+---------------------+---------------------+
     | Directory         | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Directory         | uri                 | Sections 2.4.3 and  |
     |                   |                     | 2.10.4              |

okay bestie, the mapping table keeps going πŸŽ€ Each row pairs a JSContact type and property with the section that covers it. Here's the next batch πŸ’…βœ¨

     +-------------------+---------------------+---------------------+
     | EmailAddress      | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | EmailAddress      | address             | Section 2.7.1       |
     +-------------------+---------------------+---------------------+
     | EmailAddress      | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | EmailAddress      | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | EmailAddress      | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | LanguagePref      | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | LanguagePref      | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | LanguagePref      | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Link              | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Link              | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Link              | kind                | Section 2.9.1       |
     +-------------------+---------------------+---------------------+
     | Link              | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | Link              | mediaType           | Section 2.3.14      |
     +-------------------+---------------------+---------------------+
     | Link              | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Link              | uri                 | Sections 2.9.1 and  |
     |                   |                     | 2.11.9              |
     +-------------------+---------------------+---------------------+
     | Media             | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Media             | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Media             | kind                | Sections 2.5.7,     |
     |                   |                     | 2.9.2, and 2.11.7   |
     +-------------------+---------------------+---------------------+
     | Media             | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | Media             | mediaType           | Section 2.3.14      |
     +-------------------+---------------------+---------------------+
     | Media             | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Media             | uri                 | Sections 2.5.7,     |
     |                   |                     | 2.9.2, and 2.11.7   |
     +-------------------+---------------------+---------------------+
     | Name              | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Name              | components          | Sections 2.5.5 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Name              | defaultSeparator    | Sections 2.5.5 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Name              | full                | Section 2.5.2       |
     +-------------------+---------------------+---------------------+
     | Name              | phoneticScript      | Sections 2.3.15 and |
     |                   |                     | 2.3.19              |
     +-------------------+---------------------+---------------------+
     | Name              | phoneticSystem      | Section 2.3.15      |
     +-------------------+---------------------+---------------------+
     | Name              | isOrdered           | Sections 2.5.5 and  |
     |                   |                     | 3.3.1               |
     +-------------------+---------------------+---------------------+
     | Name              | sortAs              | Section 2.3.21      |
     +-------------------+---------------------+---------------------+
     | NameComponent     | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | NameComponent     | kind                | Section 2.5.5       |
     +-------------------+---------------------+---------------------+
     | NameComponent     | phonetic            | Section 2.3.15      |
     +-------------------+---------------------+---------------------+
     | NameComponent     | value               | Section 2.5.5       |
     +-------------------+---------------------+---------------------+
     | Nickname          | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Nickname          | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Nickname          | name                | Section 2.5.5       |
     +-------------------+---------------------+---------------------+
     | Nickname          | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Note              | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Note              | author              | Sections 2.3.2 and  |
     |                   |                     | 2.3.3               |
     +-------------------+---------------------+---------------------+
     | Note              | created             | Section 2.3.6       |
     +-------------------+---------------------+---------------------+
     | Note              | note                | Section 2.11.4      |
     +-------------------+---------------------+---------------------+
     | OnlineService     | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | OnlineService     | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | OnlineService     | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | OnlineService     | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | OnlineService     | service             | Section 2.3.20      |
     +-------------------+---------------------+---------------------+
     | OnlineService     | uri                 | Sections 2.7.2 and  |
     |                   |                     | 2.7.5               |
     +-------------------+---------------------+---------------------+
     | OnlineService     | user                | Section 2.3.24      |
     +-------------------+---------------------+---------------------+
     | OrgUnit           | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | OrgUnit           | name                | Section 2.9.4       |
     +-------------------+---------------------+---------------------+
     | OrgUnit           | sortAs              | Section 2.3.21      |
     +-------------------+---------------------+---------------------+
     | Organization      | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Organization      | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Organization      | name                | Section 2.9.4       |
     +-------------------+---------------------+---------------------+
     | Organization      | sortAs              | Section 2.3.21      |
     +-------------------+---------------------+---------------------+
     | Organization      | units               | Section 2.9.4       |
     +-------------------+---------------------+---------------------+
     | PartialDate       | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | PartialDate       | calendarScale       | Section 2.3.4       |
     +-------------------+---------------------+---------------------+
     | PartialDate       | day                 | Section 2.2.2       |
     +-------------------+---------------------+---------------------+
     | PartialDate       | month               | Section 2.2.2       |
     +-------------------+---------------------+---------------------+
     | PartialDate       | year                | Section 2.2.2       |
     +-------------------+---------------------+---------------------+
     | PatchObject       | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | PersonalInfo      | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | PersonalInfo      | kind                | Sections 2.10.1,    |
     |                   |                     | 2.10.2, and 2.10.3  |
     +-------------------+---------------------+---------------------+
     | PersonalInfo      | listAs              | Section 2.3.10      |
     +-------------------+---------------------+---------------------+
     | PersonalInfo      | level               | Section 2.3.13      |
     +-------------------+---------------------+---------------------+
     | PersonalInfo      | value               | Sections 2.10.1,    |
     |                   |                     | 2.10.2, and 2.10.3  |
     +-------------------+---------------------+---------------------+
     | Phone             | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Phone             | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Phone             | features            | Section 2.7.6       |
     +-------------------+---------------------+---------------------+
     | Phone             | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | Phone             | number              | Section 2.7.6       |
     +-------------------+---------------------+---------------------+
     | Phone             | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Pronouns          | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Pronouns          | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | Pronouns          | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | Pronouns          | pronouns            | Section 2.5.4       |
     +-------------------+---------------------+---------------------+
     | Relation          | @type               | not applicable      |

Okay bestie, this is the conversion table that wraps up Appendix A πŸ’… It maps every JSContact type and property to where it lives in the rules above, so you can always find your way back. Table 8 is the one to screenshot πŸ“Έ

     +-------------------+---------------------+---------------------+
     | Relation          | relation            | Section 2.9.5       |
     +-------------------+---------------------+---------------------+
     | Resource          | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | SchedulingAddress | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | SchedulingAddress | contexts            | Section 2.3.22      |
     +-------------------+---------------------+---------------------+
     | SchedulingAddress | label               | Section 2.11.11     |
     +-------------------+---------------------+---------------------+
     | SchedulingAddress | pref                | Section 2.3.17      |
     +-------------------+---------------------+---------------------+
     | SchedulingAddress | uri                 | Section 2.13.1      |
     +-------------------+---------------------+---------------------+
     | SpeakToAs         | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | SpeakToAs         | grammaticalGender   | Section 2.5.4       |
     +-------------------+---------------------+---------------------+
     | SpeakToAs         | pronouns            | Section 2.5.4       |
     +-------------------+---------------------+---------------------+
     | AddressComponent  | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | AddressComponent  | kind                | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | AddressComponent  | value               | Section 2.6.1       |
     +-------------------+---------------------+---------------------+
     | Timestamp         | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Timestamp         | utc                 | Section 2.2.2       |
     +-------------------+---------------------+---------------------+
     | Title             | @type               | not applicable      |
     +-------------------+---------------------+---------------------+
     | Title             | kind                | Section 2.9.6       |
     +-------------------+---------------------+---------------------+
     | Title             | name                | Section 2.9.6       |
     +-------------------+---------------------+---------------------+
     | Title             | organizationId      | Section 2.9.6       |
     +-------------------+---------------------+---------------------+

        Table 8: Conversion Rules for JSContact Types and Properties

Acknowledgements 🫢

The definition and examples of the PHONETIC (Section 2.3.15) and SCRIPT (Section 2.3.19) parameters are based on the initial draft version of [vOBJECT]. So the whole vibe of those two parameters was inspired by an early draft of [vOBJECT] 🌸 Big credit where it's due! ✨

Authors' Addresses πŸ¦‹

Here's where to find the authors, with their contact info exactly as published πŸ’œ

Mario Loffredo
IIT-CNR/Registro.it
Via Moruzzi, 1
56124 Pisa
Italy
Email: mario.loffredo@iit.cnr.it
URI:   https://www.iit.cnr.it
Robert Stepanek
Fastmail
PO Box 234
Collins St. West
Melbourne VIC 8007
Australia
Email: rsto@fastmailteam.com
URI:   https://www.fastmail.com

And that's the whole RFC, bestie! πŸŒˆπŸ‘‘ We made it through all twelve parts. Iconic behaviour from everyone involved πŸ§šπŸ’–

πŸ“¦ where this page comes from