JRD, the Other Resource Descriptor

(Yes, that was a LRDD-inspired pun.)

XRD 1.0 is the result of 5 years of community development and actual deployment experience. It represents the most concise, yet extensible way to describe web resources using well understood constructs such as links. It uses XML as its extensible backbone, enabling protocols to extend pretty much every element as needed. For a long time, XML was the source of XRD’s (and its predecessor, XRDS’s) extensibility.

But XML is no longer what puts the ‘X’ in XRD. XRD utilizes the Web Linking framework for accomplishing cross-format interoperability of link relation types, as well as URI-namespaced key-value properties (for both the resource properties and links). XRD 1.0 is extensible without having to define new elements or attributes. It is accomplished simply by using its <Link> and <Property> elements as-is.

There might be cases where protocols will want to extend the schema, and that is where the XML foundation comes in handy. In addition, XML provides a mechanism for digital signature (which has as many critics as fans), and a clean way to add new elements without name collisions.

However, XML is a heavy format, and is no longer the format of choice in many new web protocols. JSON, a simple but powerful serialization format is getting more and more popular. OAuth 2.0 is likely to support JSON, following its adoption by popular services such as Twitter and Facebook as the default format of their APIs.

Introducing JRD

JRD, pronounced “Jared” and stands for JSON Resource Descriptor, is a JSON-formatted XRD document. It takes the XRD schema and converts it to a JSON structure, giving up some XML-based features, but gaining simplicity and adaptability to JSON-centric protocols and applications. JRD is based on a few simple rules:

  • XRD is the canonical representation; JRD is meant as an alternative format offered in addition to XRD.
  • JRD does not include support for new extension objects (XRD elements); it is meant for cases where the core XRD elements are sufficient.
  • XRD can be converted to JRD; a lossless conversion of JRD back to XRD is not always possible.
  • Obtaining JRD is designed as a special case request for an XRD using the HTTP Accept header or format request parameter; JRD is available where XRD is available.

In other words, services should continue using XRD as the primary format for their descriptor documents, and XRD should remain the default format for resource descriptors using the XRD schema. However, services may also support obtaining a JRD version of the document by allowing clients to specify a preference for JSON instead.

JRD supports the following XRD elements: <Subject>, <Alias>, <Expires>, <Property>, <Link>, and <Title>, as well as the attributes of the <Link>, <Property>, and <Title> elements. It does not support digital signatures.

Since nothing explains formats better than examples, the following fully-featured XRD document:


<?xml version='1.0' encoding='UTF-8'?>
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>

  <Subject>http://blog.example.com/article/id/314</Subject>
  <Expires>2010-01-30T09:30:00Z</Expires>

  <Alias>http://blog.example.com/cool_new_thing</Alias>

  <Property type='http://blgx.example.net/ns/version'>1.2</Property>
  <Property type='http://blgx.example.net/ns/ext' />

  <Link rel='author' type='text/html'
        href='http://blog.example.com/author/steve'>
    <Title>About the Author</Title>
    <Title xml:lang='en-us'>Author Information</Title>
    <Property type='http://example.com/author/role'>editor</Property>
  </Link>

  <Link rel='author' href='http://example.com/author/john'>
    <Title>The other guy</Title>
  </Link>

  <Link rel='copyright' href='http://example.com/copyright' />
</XRD>

Is represented by the following JRD document:


{
 "subject":"http://blog.example.com/article/id/314",
 "expires":"2010-01-30T09:30:00Z",
 "aliases":
 [
   "http://blog.example.com/cool_new_thing"
 ],
 "properties":
 {
   "http://blgx.example.net/ns/version":"1.2",
   "http://blgx.example.net/ns/ext":null
 },
 "links":
 {
   "author":
   [
     {
       "type":"text/html",
       "href":"http://blog.example.com/author/steve",
       "title":"About the Author",
       "titles":
       {
         "en-us":"Author Information"
       },
       "properties":
       {
         "http://example.com/author/role":"editor"
       }
     },
     {
       "href":"http://example.com/author/john",
       "title":"The other guy"
     }
   ],
   "copyright":
   [
     {
       "href":"http://example.com/copyright"
     }
   ]
 }
}

JRD does not support extension XRD elements or attributes. Future specification with use cases for extending JRD can define how to avoid name collisions (such as using a public wiki, registry, or namespaces).

Obtaining a JRD Document

In general, endpoints should not return a JRD representation by default. They should return an XRD document. Clients looking for a JRD representation make their preference known by using the HTTP ‘Accept‘ header with the ‘application/xrd+json‘ media type, or include the ‘format‘ parameter with a value of ‘json‘ in the request (or both).

For example, requesting a host-meta using JRD:


> GET /.well-known/host-meta?format=json HTTP/1.1
> Host: example.com
> Accept: application/xrd+json

Updates

5/24: Removed extensibility, changed array names to plural, turned links into a hashed list using rel values. Added title and titles object for the simple and complex use cases. Changed mime type to application/xrd+json.

5/14: Changed ‘namespace’ to ‘ns’ and ‘title’, ‘ns’, and ‘properties’ from array of objects to an object.

22 thoughts on “JRD, the Other Resource Descriptor

  1. Looks good to me. I would even go one step further with “namespace” and just call it “ns” and include a required “default” namespace pointing to JRD. That way if someone wanted to come along and create an alternative to JRD (maybe a lossless conversion) it would be easier to solidly check what format we’re dealing with.

    • Chancing namespace to ns is a good idea. I’ll consider it. However, the default namespace is going to be defined when the JRD spec is published but will remain implicit in the format. I’m trying not to invent namespaces in JSON – that would be missing the point. Just want to allow some simple extensions to live in both worlds. Still trying to figure out some basic conversion rules for extensions.

  2. Thanks for writing this up, Eran. I’ve become more interested in JSON lately for the formats and protocols of the open, social web, and am glad to see XRD have a JSON representation.

    I also think that we should exercise caution around importing namespaces into JRD off the bat… from my impressions, namespaces are somewhat anathema to the simplicity that JSON developers prefer…

    If namespaces are a must, perhaps we could put them in the envelope of the JSON-C format?

    http://code.google.com/apis/youtube/2.0/developers_guide_jsonc.html

    • Namespaces are required at some level for simple use cases like host-meta. Since host-meta uses an extension element, and host-meta is a critical component of all new discovery work, we need to accommodate it in JRD. Being able to perform discovery end-to-end without using XML is the whole point. What I am looking to do is come up with a small and simple set of rules of importing namespaces from XRD to JRD in a way that is intentionally limited. For example, only allow child elements of without any attributes to make the transition. I am also considering getting rid of namespace aliases and just going with { “http://host-meta.net/ns/1.0#Host”:”example.com” }.

  3. Eran-thanks for taking the time to write this up! Glad I’m not the only one who really wants a JSON representation of XRD! :)

    Actually, I recently made my own attempt at a JSON format for XRD, and it’s very similar to your proposal, but with a few differences. I added support for it to DeWitt’s existing webfinger client, but with a new URL endpoint that will take an arbitrary XRD file and spit it out as JSON, e.g.:

    http://webfingerclient-dclinton.appspot.com/xrd?url=http://josephsmarr.com/xrd/simple.xml&format=json&pretty=true

    http://webfingerclient-dclinton.appspot.com/xrd?url=http://josephsmarr.com/xrd/signed.xml&format=json&pretty=true

    http://webfingerclient-dclinton.appspot.com/xrd?url=http://josephsmarr.com/xrd/complete.xml&format=json&pretty=true

    The differences in the JSON format I proposed are:
    1) I pluralized the list-valued fields (e.g. “properties” and “aliases” instead of “property” and “alias”). I think these are more readable and semantically clear (e.g. xrd.links[0].href), and there’s still a clear 1:1 mapping to the XML
    2) I explicitly made “type” and “value” sub-fields of “properties”, rather than keying them off of the type URI, because I believe the spec says you can have multiple properties with the same type-URI but different other attributes.
    3) However I *did* assume one-title-per-language, e.g. “titles”: { “en”: “English Title”, “de”: “German Title” }, because I think that’s a reasonable assumption (why have multiple english titles), and it’s also far more useful to be able to just say titles.en rather than having to iterate thru the list to find the english one to use.

    What do you think?
    Thanks, js

    • I considered using plural names for 0-or-more elements but decided against it. It makes automatic conversion of elements easier to do (I am also thinking of capitalizing the names to keep the XML schema name unchanged). This is evident in the conversion of the host-meta extension . Since this is an extension, it will not be directly specified in the JRD format, but instead generated using the namespace rules. Keeping the name the same even for lists makes this possible without a manual paperwork approach for each extension.

      While you can have multiple properties with the same type, you shouldn’t. Same story with titles. XRD parsing follows the simple ‘stop after first match’ rule, so multiple properties using the same type goes against that design. If you need multiple values, just figure a way to separate them in one string.

      • I hear you on the xml->JSON translation issue. We struggled with the same thing when designing Portable Contacts, and it seems like the choice always boils down to: “pretty XML; pretty JSON; 1:1 mapping — choose 2″. In PoCo, we solved this with “pretty JSON; 1:1 mapping; so-so XML” (i.e. repeated … tags, one for each email address), but at least the JSON was pretty and there was no translation logic required. In this case, I’m arguing for “pretty XML; pretty JSON; not-quite-1:1-mapping”, since the mapping is still simple and well-defined, and this way both XML and JSON consumers get something that makes sense. It’s a small extra bruden on providers, but it makes life better for consumers, and I think that’s the right balance (much as we’re doing now with response formats in OAuth 2.0).

        As for one-value-per-type/language, I agree with your simplifying assumption (“just don’t use more than one, since the consumer just wants to pick the first one they find”), but you’re not seizing the payoff of that approach by having an actual key-value map for the JSON representation. Instead, you have a list of objects, each with their own single key-value, which means the consumer still has to iterate through each sub-node, rather than just looking for the one they want, so I’d suggest hoisting those up, as I did with language in my example.

        Thanks, js

      • Agreed with Joseph’s points. I’d also suggest avoiding complicated namespaces in favor of lightweight conventions — since JSON uses strings for keys, it’s not at all hard to use something like “myext:keyname” for extensions (and then you could use the same conventional short ns name for both XML and JSON).

        I’d also suggest that the links be collected by relvalue, yielding easier and shorter JSON while giving up basically nothing:

        “links”: {
        “license”: [...]
        “lrdd”: [...]
        }

        in many common languages, this lets you write things like links.license[0].href and “for link in links.license …”

      • Joseph:

        I agree with your comment on the ‘title’ object structure (instead of an array of objects) and applied it also to the ‘property’ object. Good call.

        I disagree that not using plural names makes JRD ugly. It keeps it consistent and doesn’t take anything away from readability. Especially considering that many of these zero-to-many will usually include one value (like title or alias).

        We can do a lot to make JRD simple and consistent with the JSON spirit. But we do need to accommodate a basic extensibility model that will at least cover the host-meta use case. Baking the host-meta element into JRD is unacceptable to me, the same way baking into XRD was a non-starter.

        John:

        I agree about namespaces, which is why I changed the ‘ns’ object to optional. If it is not there, and the client sees a prefix: before a key name, it can ask for the XRD representation and grab the namespace declaration from there (which is easy to do even without an XML parser). However, providers can be nice and include the namespace URI at the bottom using a very simple object.

        As for links, how do you deal with multiple links with the same relation type or without any relation type? I started my draft doing just that but then realized it breaks the unique key rule.

      • > Especially considering that many of these zero-to-many will usually include one value (like title or alias).

        But I hope/assume that you’ll keep those “plural fields” always having an array/dict as values, even when they happen to only contain one value, right? So then you’ll still always have to say xrd.link[0].href, which is a bit weirder than xrd.links[0].href, though not a disaster, as you say.

        Overall, I’m quite happy with the format now, so consider this a last plea for plural fields (they improve readability and transparent semantics, and are still 1:1 with XML tags, and most developers will just pick one or the other to consume, so they won’t care that the tag names aren’t identical), but I don’t consider this a “deal-killer”, just a nice-to-have improvement. :)

        Thanks, js

      • I’ll think about it. The only reason is to maintain consistency between the core elements and extensions (where adding a plural suffix isn’t really possible without creating some spelling mistakes).

        How would you feel about having both “links” and “host”, both as arrays?

      • I guess I’d prefer plural naming for core XRD fields, even if extensions aren’t pluralized (since I think XRD will be used in many more places than host-meta). But why can’t you have “hosts”? :) Seems like you have to specify the JSON format and/or translation rules *somewhere*, and if they all say “plural fields need plural names” and/or list the names explicitly, I can’t imagine that being a trainwreck. And we’re gonna have a sweet set of open-source / hosted conformance and validation tools, so people won’t accidentally spell their tags incorrectly, right? ;)

      • Extension names will be generated by machines doing automatic translations… That’s the issue. The idea that ever XRD extension will also have to define its JRD extension is what I’m trying to avoid. For example, I don’t want host-meta to talk about JRD at all, just XRD. So where will “hosts” be defined? The whole point of JRD is automatic conversion of any XRD.

  4. In many use cases (a REST API) only a single relhref link is required, as opposed to fhe full type, titles, properties etc . No good answer here is apparent. One possibility is alternate formats with the burden placed in the library for dealing with JRD.

    links is a reserved field name for, well links. (Note: OData uses $ for various metafields.). $links: ….????
    A propertywithin a links object denotes a relationship (rel), author, copyright etc.

    The rel fields value may be a list OR a string. If it is a string then single href format is being used and the value is to be interpreted as the href. If it is a list then multiple href format is being used as above.

    Giving:

    “links”: {“author”: [ ....], “copyright”: “http://example.com/copyright”},

    • I don’t like this. I think the title optimization *might* be worthwhile but links is such a critical component that clients will have to support the more complex version anyway and simply asking for links["copyright"][0] is easy enough.

Comments are closed.