2013-05-28

Time for an updated Activity Streams?

The other day I mentioned that there's been some movement in the Activity Streams world around a new proposal to add Actions and Activities to Schema.org. There are quite a few good things in that proposal but the one downside is that it's somewhat incompatible with the current JSON Activity Streams 1.0 syntax.

So.. in order to address that incompatibility somewhat... as well as to scratch a few itches I've had after implementing Activity Streams 1.0 a bunch, I decided to create a draft of what I think a JSON Activity Streams 2.0 ought to look like.

Keeping in mind that this is just a draft and has no official standing at this point, I wanted to get this out there for folks to start reviewing. The updated syntax is designed to be directly compatible with JSON-LD. Let's take a look at the simple example from the spec:

{
  "@type": "post",
  "published": "2011-02-10T15:04:55Z",
  "actor": {
    "@type": "person",
    "@id": "urn:example:person:martin",
    "name": "Martin Smith",
    "url": "http://example.org/martin",
    "image": {
      "@id": "http://example.org/martin/image",
      "width": 250,
      "height": 250
    }
  },
  "object" : {
    "@id": "urn:example:blog:abc123/xyz"
    "url": "http://example.org/blog/2011/02/entry"
  },
  "target" : {
    "@type": "blog",
    "@id": "urn:example:blog:abc123",
    "name": "Martin's Blog",
    "url": "http://example.org/blog/"
  }
}

This example showcases a number of the key differences between 1.0 and the proposed 2.0 syntax.

  1. "verb" and "objectType" both become "@type" ... this combines both into a common type model that can be shared with other Linked Data vocabularies (and Schema.org).
  2. "id" becomes "@id" ... this is just for alignment with JSON-LD.
  3. "displayName" becomes just "name" ... this is for alignment with Schema.org.
  4. The notion of a "Media Link" is replaced with a "Link Value" model. Read the spec for details on how this works. The short version is that we get Link Relations support in a way that is JSON-LD and Schema.org compatible and gives us a great deal more flexibility than the older "Media Link" definition.

To really draw out the differences, let's look at the extended example from the spec:


{
  "items" : [
    {
      "@type": "post",
      "@language": "en",
      "published": "2011-02-10T15:04:55Z",
      "foo": "some extension property",
      "generator": "http://example.org/activities-app",
      "provider": "http://example.org/activity-stream",
      "title": {
        "en": "Martin posted a new video to his album.",
        "ga": "Martin phost le fisean nua a albam."
      },
      "actor": {
        "@type": "person",
        "@id": "urn:example:person:martin",
        "name": "Martin Smith",
        "url": "http://example.org/martin",
        "foo2": "some other extension property",
        "image": {
          "@id": "http://example.org/martin/image",
          "width": 250,
          "height": 250
        }
      },
      "object" : {
        "@type": "photo",
        "@id": "urn:example:album:abc123/my_fluffy_cat",
        "url": "http://example.org/album/my_fluffy_cat.jpg",
        "image": {
          "@id": "http://example.org/album/my_fluffy_cat_thumb.jpg",
          "width": 250,
          "height": 250
        }
      },
      "target": {
        "url": "http://example.org/album/",
        "@type": "photo-album",
        "@id": "urn:example.org:album:abc123",
        "title": {
          "en": "Martin's Photo Album",
          "ga": "Grianghraif Mairtin"
        },
        "image": {
          "@id": "http://example.org/album/thumbnail.jpg",
          "width": 250,
          "height": 250
        }
      }
    }
  ]
}

There are several interesting bits in this example:

  1. Note that the values of the "generator" and "provider" properties are Strings... well, in this example they are. They are actually "Link Values", which can be either a String, an Object, or an Array of Strings and Objects. In 1.0 those property values are always objects. While that may seem a bit confusing, it's completely in line with the JSON-LD syntax rules, and it allows us to alter the verbosity of the Activity Streams document based on the needs of the publisher -- that is, if all we need is an IRI, that's all we have to provide; if we need additional metadata, however, we can easily provide it. Yes, it increases the work on the parsing end but it provides for a much more versatile model.
  2. Note that the value of the "title" property is a JSON object. Actually, to be specific, the value can either be a single String or a JSON-LD Language Map. The idea here is to provide for easy publisher-provided localization of certain natural language fields in the Activity Streams document. This has been one of the most sought after features among many of the international implementors I've spoken with.
  3. Note the use of the "@language" property, taken directly from JSON-LD. This property is used to establish the default language context for the object.

While not strictly defined as a JSON-LD vocabulary, a key goal of these syntax modifications is to make it possible to process an Activity Streams document as if it were a JSON-LD document. Someone could easily come up with a JSON-LD Context Description that describes this specific vocabulary and merges it with the Schema.org Actions model.

For instance, this example is a non-normative illustration:

{
  '@context': {
    '@id': 'http://schema.org',
    'actor': 'http://schema.org/Action/performedBy',
    'object': 'http://schema.org/BuyAction/bought',
    'purchase': 'http://schema.org/BuyAction',
    'person': 'http://schema.org/Person',
    'book': 'http://schema.org/Book'
  },
  '@type' : 'purchase',
  'startTime' : '2013-04-02T12:31-0800',
  'endTime' : '2013-04-02T12:31-0800',
  'actor': {
    '@type': 'person',
    'name': 'John Doe'
  }
  'status':'completed',
  'object': {
    '@type': 'book',
    'title': 'A Tale of Two Cities'
  }
}

Take out the "@context" property and this is just another Activity Streams 2.0 document. With the "@context" property, it becomes possible to process it just like any of the proposed Schema.org actions. (my JSON-LD @context foo is rusty so I may have some of the @context definitions a bit wrong.. but you should get the idea)

Note that it's still perfectly possible to process this Activity Streams document without any knowledge whatsoever of JSON-LD or Schema.org... which is a very good thing. Yes, there is some additional complexity on the parsing side to handle things like Language Maps and Link Values, but the new functionality enabled is well worth the tradeoff, I think.

Anyway, it's a work in progress, and I'm sure there will be many changes in the future. I'll repeat that this has absolutely no official standing in the Activity Streams community yet as I'm just now writing up my thoughts on it. (in fact, the mailing lists introduction to this draft is going to be a link to this blog post... so, yeah, things likely will evolve a bit if this modified version ends up moving forward. As always, thoughts and opinions and complaints and praise are all more than welcome.