Skip to content
Michael Angstadt edited this page Jul 24, 2020 · 6 revisions

vCard data can be encoded in JSON using the jCard format. The jCard specification is defined in RFC 7095. jCards only adhere to version 4.0 of the vCard specification. They do not support versions 2.1 or 3.0.

Below is an example of a jCard.

["vcard",
  [
    ["version", {}, "text", "4.0"],
    ["n", {}, "text", ["Doe", "John", "", "Mr", ""]],
    ["fn", {}, "text", "Mr. John Doe"],
    ["email", {"group":"group1", "type":"home"}, "text", "jdoe@example.com"],
    ["note", {}, "text", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec at lacus justo. Phasellus quis nisl eget augue gravida tempor in at ante. Suspendisse suscipit eleifend molestie."]
  ]
]

1 Reading JSON-encoded vCard data

The JCardReader class handles the parsing of JSON-encoded vCard data. The data is read in a streaming fashion, meaning it parses the data as it is read off the wire. This results in a smaller memory footprint than other approaches.

1.1 Important methods

readNext()
Parses and returns the next VCard object in the data stream. The method returns null when the end of stream has been reached.

getWarnings()
Returns any problems the parser encountered while parsing the VCard object that was last returned by readNext(). Examples of things that could cause warnings are: malformed date values or unparseable property values.

close()
As with all I/O operations, it's important to call the close() method when you are done with the JCardReader object in order to properly close the input stream.

1.2 Example

The example below outputs the names and birthdays of each vCard in the JSON data stream.

File file = new File("vcards.json");
JCardReader reader = new JCardReader(file);
try {
  VCard vcard;
  DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
  while ((vcard = reader.readNext()) != null) {
    FormattedName fn = vcard.getFormattedName();
    String name = (fn == null) ? null : fn.getValue();

    Birthday bday = vcard.getBirthday();
    Date date = (bday == null) ? null : bday.getDate();
    String birthday = (date == null) ? null : df.format(date);

    System.out.println(name + " " + birthday);
  }
} finally {
  reader.close();
}

1.3 A note about unparseable property values

If a property's value cannot be parsed (for example, due to a malformed date value), the property is treated as an extended property and a warning is logged. The code below demonstrates this:

String json =
"[\"vcard\"," +
  "[" +
    "[\"version\", {}, \"text\", \"4.0\"]," +
    "[\"rev\", {}, \"timestamp\", \"I don't know, like, 2 days ago?\"]" +
  "]" +
"]";

JCardReader reader = new JCardReader(json);
VCard vcard = reader.readNext();
reader.close();

List<String> warnings = reader.getWarnings();
System.out.println("Warnings: " + warnings);

System.out.println("REV property: " + vcard.getRevision());

RawProperty prop = vcard.getExtendedProperty("REV");
System.out.println("Extended property: " + prop.getValue());

The above code produces the following output. The comma characters are escaped to simulate how the value would appear in a plain-text vCard.

Warnings: [Line 1 (rev property): Property value could not be parsed.  It will be saved as an extended property instead.
  Reason: Could not parse date string.
  Value: I don't know\, like\, 2 days ago?]
REV property: null
Extended property: I don't know\, like\, 2 days ago?

2 Writing JSON-encoded vCard data

The JCardWriter class handles the serialization of JSON-encoded vCard data.

2.1 Important methods

write()
Writes the contents of an VCard object to the data stream.

close()
As with all I/O operations, it's important to call the close() method when you are done with the JCardWriter object in order to properly close the output stream. It's especially important for JCardWriter because it must write the proper closing characters to complete the JSON syntax.

2.2 Example

The example below writes a list of VCard objects to a JSON file.

List<VCard> vcards = ...
File file = new File("vcards.json");
JCardWriter writer = new JCardWriter(file);
try {
  for (VCard vcard : vcards) {
    writer.write(vcard);
  }
} finally {
  writer.close();
}

3 Dependency

If your application does not require jCard functionality, you can exclude the "jackson-core" dependency from your build.

<dependency>
  <groupId>com.googlecode.ez-vcard</groupId>
  <artifactId>ez-vcard</artifactId>
  <version>...</version>
  <exclusions>
    <!-- jCard parsing not needed -->
    <exclusion>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>