This document describes a JSON serialization format to describe simple streams of data as well as single objects of data for data transfer and processing.

Author's Note

This document is an attempt to unify various simplified versions of the Microformats-2 representative JSON format. As such, much of this document is likely to change as various implementations contribute input.

This document is being drafted as a Non-Rec Track document, and is intended to end up a Working Group Note to describe one potential minimal method of representing a social web object.

Introduction

JF2 is a JSON based document format that describes lists and single entries of information. The primary use case for JF2 is to create a JSON format for social web post objects to be processed directly by client software and by other servers.

The name JF2 comes from its origins in being a direct parsed format of Microformats-2 (MF2) data from html. Rather than defining a new vocabulary, JF2 uses the vocabulary defined by [[microformats2]] however any other suitable vocabulary.

It is relevant to note that JF2 objects have been most useful as programming objects, not as a serialization format. This document using javascript object notation for serializing to explain structure, but any language will have its own native structure in which JF2 would be stored.

Use Cases

JF2 has evolved as a result of a variety of use-cases for different implementations exploring ways to simplify their existing use of canonical parsed microformats2 JSON output. All of these use cases in particular are simply to have a single format for the storage and use of social web objects.

Webmention.io is a service that provides webmention processing and verification on behalf of other sites. It uses a simple JSON object to transfer a processed webmention back to the client site's javascript for display. The attributes are intended to be processed only by the client site's javascript code, not by anything else.

mf2util is a utility library that provides a layer on top of microformats processing. The library returns only a simple JSON object and strips off any unnecessary information leaving the library user only the most essential information.

Various services (xray, unmung, socialstreams) provide conversion from microformats pages in to JF2 for quick inspection to validate proper semantics.

Syntax

JF2 consists of JSON objects which are defined by a type property that will specify the vocabulary of the object. Properties are attached to these objects which will contain either a single string, a single object, an array of strings, or an array of objects. Arrays that have only a single item SHOULD be condensed into only the single containing item. Any property of an object MAY be a single item or an array of items except for reserved words defined below.

Reserved Keywords

The following keywords are reserved and cannot be used as property names in vocabularies.

Posts

Post Objects

A post is composed of a "type" property, and one or more additional properties that describe the post.

The "type" property has a value that describes the vocabulary of this post. Common values include "entry", "card", etc. See Microformats 2 vocabularies for the full list when using a microformats based vocabulary.

Any additional properties in the post object are considered part of the post's vocabulary.

Post Properties

The list of valid post properties is defined by the vocabularies. This allows new vocabularies to be developed outside the development of the syntax.

Most values will be strings. If a property (such as `author` for example) references another object, it may be serialized in two ways: as an object serialized as the property value or as the unique identifier or URL where the object can be found. See Using References

Values may also be arrays if the vocabulary allows for multiple values of the property.

Example Post

            {
              "type": "entry",
              "published": "2015-10-20T15:49:00-0700",
              "url": "http://example.com/post/fsjeuu8372",
              "author": {
                "type": "card",
                "name": "Alice",
                "url": "http://alice.example.com",
                "photo": "http://alice.example.com/photo.jpg"
              },
              "name": "Hello World",
              "content": "This is a blog post",
              "category": "Posts"
            }
          
            {
              "type": "entry",
              "published": "2015-10-20T15:49:00-0700",
              "url": "http://example.com/like/r23eugi02c",
              "author": {
                "type": "card",
                "name": "Alice",
                "url": "http://alice.example.com",
                "photo": "http://alice.example.com/photo.jpg"
              },
              "like-of": "http://bob.example.com/post/100",
              "category": ["Likes", "Posts"]
            }
          

Author

An author is represented by the h-card vocabulary, and consists of a name, photo URL, URL to the author profile, and [others](http://microformats.org/wiki/h-card). This is represented by the following JSON.

          {
            "type": "card",
            "name": "Aaron Parecki",
            "photo": "http://aaronparecki.com/photo.jpg",
            "url": "http://aaronparecki.com/"
          }
        

HTML Content

By default, any string value should be interpreted as literal plaintext. This means when displaying a string in an HTML page, it must be HTML escaped.

If the value of a property is to be interpreted as HTML, it MUST be enclosed in an object noting its content-type as follows.

          {
            "type": "entry",
            "content": {
              "content-type": "text/html",
              "value": "<b>Hello World</b>"
            }
          }
        

Note that only one content-type is allowed and also only one entry is given under content. It is usually preferrable to select the most expressive option for this. So it is preferrable to select the html content-type over plaintext for the content property.

Multiple URLs for video/audio/picture

Since HTML video/audio/picture tags may have multiple URLs, we need a way to convey this information in the JSON representation.

            <div class="h-entry">
              <video class="u-video" width="640" height="360" preload controls>
                <source src="sample_h264.mov" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
                <source src="sample_ogg.ogv" type='video/ogg; codecs="theora, vorbis"' />
                <source src="sample_webm.webm" type='video/webm; codecs="vp8, vorbis"' />
              </video>
            </div>
          
            {
              "type": "entry",
              "video": [
                {
                  "content-type": "video/mp4",
                  "url": "sample_h264.mov"
                },
                {
                  "content-type": "video/ogg",
                  "url": "sample_ogg.ogg"
                },
                {
                  "content-type": "video/webm",
                  "url": "sample_webm.webm"
                }
              ]
            }
          

Using References

The purpose of the `references` property is to exclude any non-authoritative data from the defined object. To do this, non-authoritative data is moved so that implementations looking to process only authoritative data may simply ignore the references property and fetch any data that would be contained there from its authoritative source.

If a property is a reference to an object that is defined authoritatively in some other location, the `references` property SHOULD be used. The property SHOULD contain only the unique identifier or URL where the authoritative data may be found. In the references object, the URL or unique identifier MAY be entered as the key field and a serialization of the referenced object MAY be provided. This serialization of the referenced object MAY be incomplete so as to provide only necessary data.

Parsing implementations SHOULD fetch data from the authoritative source instead of using the references object.

Example of References

            {
              "type": "entry",
              "published": "2015-10-20T15:49:00-0700",
              "url": "http://example.com/post/fsjeuu8372",
              "author": "http://alice.example.com",
              "name": "Hello World",
              "content": "This is a blog post",
              "category": "Posts",
              "references": {
                "http://alice.example.com": {
                  "type": "card",
                  "name": "Alice",
                  "url": "http://alice.example.com",
                  "photo": "http://alice.example.com/photo.jpg"
                }
              }
            }
          
            {
              "type": "entry",
              "published": "2015-10-20T15:49:00-0700",
              "url": "http://example.com/like/r23eugi02c",
              "author": {
                "type": "card",
                "name": "Alice",
                "url": "http://alice.example.com",
                "photo": "http://alice.example.com/photo.jpg"
              },
              "like-of": "http://bob.example.com/post/100",
              "category": ["Likes", "Posts"],
              "references": {
                "http://bob.example.com/post/100": {
                  "type": "entry",
                  "published": "2015-10-18T12:33:00-0700",
                  "url": "http://bob.example.com/post/100",
                  "author": "http://bob.example.com",
                  "name": "My First Post",
                  "content": "This is my first post on my new blog, I hope you like it"
                },
                "http://bob.example.com": {
                  "type": "card",
                  "name": "Bob",
                  "url": "http://bob.example.com",
                  "photo": "http://bob.example.com/mypicture.jpg"
                }
              }
            }
          

Collections

Posts can live inside of collections. A collection may be a home page feed, or a feed of other posts such as a list of contacts, a list of things someone has liked, etc. There is no requirement that all posts in a collection need to be of the same type.

The collection may also have its own properties such as "name" or "author".

        {
          "type": "feed",
          "url": "http://alice.example.com/collectionurl",
          "name": "Alice's Home Page",
          "author": {
            "type": "card",
            "name": "Alice",
            "url": "http://alice.example.com",
            "photo": "http://alice.example.com/photo"
          },
          "children": [
            { ... },
            { ... }
          ]
        }
      

Multiple items on a page

If an HTML page contains multiple top-level items, (most commonly found when a page contains a list of [[h-entry]] objects), the parser creates an implicit top-level collection with no properties.

          {
            "children": [
              { ... },
              { ... }
            ]
          }
        

Deriving the Syntax

This syntax is derived from HTML with Microformats-2, converted to JSON [[microformats2-parsing]] converted to a simplified JSON. The examples below illustrate the process.

Deriving a Note

HTML + Microformats

          <article class="h-entry">
            <h1 class="p-name">Hello World</h1>
            <p>Published by <a class="p-author h-card" href="http://example.com/">A. Developer</a>
               on <a href="http://example.com/2015/10/21" class="u-url"><time class="dt-published" datetime="2015-10-21T12:00:00-0700">October 21<sup>st</sup>, 2015</time></a>
           
            <p class="p-summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.</p>
           
            <div class="e-content"><p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p></div>
          </article>
        

Parsed Microformats JSON

        {
          "items": [
            {
              "type": [
                "h-entry"
              ],
              "properties": {
                "author": [
                  {
                    "type": [
                      "h-card"
                    ],
                    "properties": {
                      "name": [
                        "A. Developer"
                      ],
                      "url": [
                        "http:\/\/example.com\/"
                      ]
                    },
                    "value": "A. Developer"
                  }
                ],
                "name": [
                  "Hello World"
                ],
                "summary": [
                  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar."
                ],
                "url": [
                  "http:\/\/example.com\/2015\/10\/21"
                ],
                "published": [
                  "2015-10-21T12:00:00-0700"
                ],
                "content": [
                  {
                    "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
                    "value": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
                  }
                ]
              }
            }
          ]
        }
        

Simplified JSON

        {
          "type": "entry",
          "author": {
            "type": "card",
            "url": "http://example.com",
            "name": "A. Developer"
          },
          "url": "http://example.com/2015/10/21",
          "published": "2015-10-21T12:00:00-0700",
          "name": "Hello World",
          "summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.",
          "content": {
            "value": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
            "content-type": "text/html"
          }
        }

        

JSON-LD Consideration

JF2 documents all have an implicit @context field which is optional. This @context can be found at http://www.w3.org/ns/jf2 and is provided only to make conversion to [[JSON-LD]] format possible. Most JF2 will process fine in JSON-LD systems, however, this support is not guaranteed and those wishing to use JF2 in JSON-LD may need to modify serialization slightly.

Implementations

The following is a list of currently known implementations of JF2-like formats and their current differences to this document

Webmention.io

Webmention.io is a hosted service for handling webmentions. Webmentions are accessed from an API that that returns a set of objects in JSON format similar to JF2. The key difference is the inclusion of some additional data wrapping the objects (source, verified, verified_data, etc) and all wrapped in a "links" array. Code available at https://github.com/aaronpk/webmention.io

XRay

X-Ray is a tool to return structured data from any URL. Code available at https://github.com/aaronpk/XRay

Unmung

Unmung is a tool for converting various formats. Code available at https://github.com/kevinmarks/unmung

SocialStreams

SocialStreams is a translation service for converting social formats. Code available at https://github.com/dissolve/socialstream

mf2util

Mf2util is a utility library for interpreting microformats2. Code available at https://github.com/kylewm/mf2util

Acknowledgements

The authors wish to thank the Microformats, IndieWebCamp, Pump.io, and Activity Streams communities for their continued work in building the social web and helping define standards such as this one. This includes, but is certainly not limited to, Aaron Parecki, Benjamin Goering, Christopher Webber, Dave Wilkinson II, James Snell, Kyle Mahan, and Tantek Çelik.