Import and export PDF annotations from Instant JSON on Android

Instant JSON is our approach to bringing annotations into a modern format while keeping all important properties to make the Instant JSON spec work with PDF. It’s fully documented and supports long-term storage.

Instant JSON stores a list of new or updated annotations. Annotations follow the format for Instant JSON for annotations. When an annotation contains a pdfObjectId, it’s considered to be an update to one of the annotations of the original PDF. For newly created annotations, this key won’t be set.

There are some limitations with Instant JSON, in that not all annotation types are currently supported, and only the properties that can be handled correctly across all of Nutrient’s supported platforms (iOS, Android, Web, Windows, and Document Engine) are serialized. For more information, check out the detailed JSON format guide.

Exporting annotations

To serialize an Annotation and export it to its JSON representation, you can call annotation.toInstantJson(). For example:

// Serializes a single annotation to a JSON string.
val json: String = annotation.toInstantJson()
// Serializes a single annotation to a JSON string.
final String json = annotation.toInstantJson();

The string will contain a human-readable JSON. Here’s an Instant JSON sample payload for an ink annotation:

{
  "v": 1,
  "type": "pspdfkit/ink",
  "bbox": [89, 98, 143, 207],
  "blendMode": "normal",
  "createdAt": "2018-07-03T13:53:03Z",
  "isDrawnNaturally": false,
  "lineWidth": 5,
  "lines": {
    "intensities": [
      [0.5, 0.5, 0.5],
      [0.5, 0.5, 0.5]
    ],
    "points": [
      [
        [92, 101],
        [92, 202],
        [138, 303]
      ],
      [
        [184, 101],
        [184, 202],
        [230, 303]
      ]
    ]
  },
  "opacity": 1,
  "pageIndex": 0,
  "strokeColor": "#AA47BE",
  "updatedAt": "2018-07-03T13:53:03Z"
}

Importing annotations

To create an annotation from an existing Instant annotation JSON, use createAnnotationFromInstantJson() from your document’s AnnotationProvider. For example:

// Deserialize an Instant annotation JSON and create an annotation from it.
val annotation: Annotation = document
    .getAnnotationProvider()
    .createAnnotationFromInstantJson(json)
// Deserialize an Instant annotation JSON and create an annotation from it.
final Annotation annotation = document
    .getAnnotationProvider()
    .createAnnotationFromInstantJson(json);
Information

The created Annotation will automatically be added to the PdfDocument of the used AnnotationProvider during deserialization.

Instant JSON annotation attachment API

The Instant JSON annotation attachment API enables you to represent an annotation’s binary attachments as data blobs. For example, a stamp annotation with an image has an attachment.

Importing image annotations

To import an image annotation, you need to perform a two-step operation:

override fun onDocumentLoaded(document: PdfDocument) {
        super.onDocumentLoaded(document)

        val jsonData = "{"bbox": [170.78128051757812, 219.125, 249.99993896484375, 249.99993896484375], "createdAt": "2021-11-02T15:32:58Z", "creatorName": "simone", "imageAttachmentId": "566", "name": "bc8a9057-c000-4adb-b438-8731f42e5814", "opacity": 1, "pageIndex": 0, "rotation": 0, "type": "pspdfkit/image", "updatedAt": "2021-11-02T15:33:24Z", "v": 1}"
        val anotherStampAnnotation = document.annotationProvider.createAnnotationFromInstantJson(jsonData)

        val tempBinaryAttachmentJsonFile = File("image/stamp.jpeg")
        anotherStampAnnotation.attachBinaryInstantJsonAttachment(FileDataProvider(tempBinaryAttachmentJsonFile), "image/jpeg")
override
private void onDocumentLoaded(PdfDocument document){
  super.onDocumentLoaded(document);

    String jsonData = "{"bbox": [170.78128051757812, 219.125, 249.99993896484375, 249.99993896484375], "createdAt": "2021-11-02T15:32:58Z", "creatorName": "simone", "imageAttachmentId": "566", "name": "bc8a9057-c000-4adb-b438-8731f42e5814", "opacity": 1, "pageIndex": 0, "rotation": 0, "type": "pspdfkit/image", "updatedAt": "2021-11-02T15:33:24Z", "v": 1}";
    StampAnnotation anotherStampAnnotation = document.annotationProvider.createAnnotationFromInstantJson(jsonData);

    File tempBinaryAttachmentJsonFile = new File("image/stamp.jpeg");
    anotherStampAnnotation.attachBinaryInstantJsonAttachment(new FileDataProvider(tempBinaryAttachmentJsonFile), "image/jpeg");

}

Exporting image annotations

To export an image annotation:

  • Convert the annotation to Instant JSON annotation using the Annotation#toInstantJson() method.

  • Fetch the binary Instant JSON attachment and write the binary into another file using the fetchBinaryInstantJsonAttachment method. At the end of the exporting process, you’ll end up with two files — one containing the JSON data, and another one containing the binary Instant JSON attachment.

val jsonData = stampAnnotation.toInstantJson()

val tempBinaryAttachmentJsonFile = File.createTempFile("tmp_", "stampAnnotationBinaryJsonAttachment.jpeg")
val outputStream = FileOutputStream(tempBinaryAttachmentJsonFile)

if (stampAnnotation.hasBinaryInstantJsonAttachment()) {
    stampAnnotation.fetchBinaryInstantJsonAttachment(outputStream)
}

val tempJsonFile = File.createTempFile("tmp_", "stampAnnotationJson.txt")
FileWriter(tempJsonFile).use { w -> w.write(jsonData) }
String jsonData = stampAnnotation.toInstantJson();

File tempBinaryAttachmentJsonFile = File.createTempFile("tmp_", "stampAnnotationBinaryJsonAttachment.jpeg");
FileOutputStream outputStream = new FileOutputStream(tempBinaryAttachmentJsonFile);

if (stampAnnotation.hasBinaryInstantJsonAttachment()) {
    stampAnnotation.fetchBinaryInstantJsonAttachment(outputStream);
}

File tempJsonFile = File.createTempFile("tmp_", "stampAnnotationJson.txt");
File writer = new FileWriter(tempJsonFile);
writer.write(jsonData);
writer.flush();
writer.close();

For information on detailed use, see the catalog example for the Instant JSON attachment API.