Skip to content

Instantly share code, notes, and snippets.

@bradgessler
Last active Dec 29, 2015
Embed
What would you like to do?
JSON is too verbose for hypermedia APIs. HON (Hypermedia Object Notation) preserves the readability and implicit data structure of JSON while with the addition of line attributes for URL and pagination metadata. From http://bradgessler.com/articles/hon/
{
name: "Todo List",
items(href: '/lists/1203/items', next_href: "/lists/1203/items?page=2"): [
item(href: '/items/1'): {
description: "Pick up pizza",
status: "completed"
},
item(href: '/items/12'): {
description: "Eat pizza",
status: "non_started"
}
]
}
@bradgessler
Copy link
Author

bradgessler commented Nov 23, 2013

You wouldn't have duplicate href keys (just like you can't do that in JSON). Those could be put in the items() key attributes.

{
  name: "Todo List",
  items(href: '/lists/1203/items', next_href: "/lists/1203/items?page=2", blog_href: 'http://example.org/xxxxx', avatar_href: 'http://example.org/yyyyy'): [
    item(href: '/items/1'): {
      description: "Pick up pizza",
      status: "completed"
    },
    item(href: '/items/12'): {
      description: "Eat pizza",
      status: "non_started"
    }
  ]
}

The use case you're describing sounds like HTML and a web browser.

@mamund
Copy link

mamund commented Nov 26, 2013

So, to make sure I have your design in my head correctly, if there are multiple links for a single item (e.g. my home page, my twitter account, my photo album, etc.) you'd make these structural elements in the item body like this:

{
  name: "Todo List"
  items(href: '/lists/1203/items', next_href: "/lists/1203/items?page=2"): [
    item(href: '/items/1'): {
      description: "Pick up pizza",
      status: "completed",
      blog_href: "http://example.org/xxxxx",
      avatar_href: "http://example.org/yyyyy"
    },
    item(href: '/items/12'): {
      description: "Eat pizza",
      status: "non_started",
      blog_href: "http://example.org/qqqqqq",
      avatar_href: "http://example.org/zzzzzz"
    }
  ]
}

now, how would i know (when writing the client app) that one of those hrefs should be treated as inline and the other as a navigation?

@bradgessler
Copy link
Author

bradgessler commented Nov 30, 2013

I would limit the key attributes ({key(attributes): value}) to hrefs that help HON client load and navigate datasets from the service.

{
  list(href: '/lists/1'): {
    name: "Todo List",
    items(href: '/lists/1203/items', next_href: "/lists/1203/items?page=2"): [
      item(href: '/items/1'): {
        blog_href: "http://example.org/xxxxx",
        avatar_href: "http://example.org/yyyyy",
        description: "Pick up pizza",
        status: "completed"
      },
      item(href: '/items/12'): {
        blog_href: "http://example.org/qqqqqq",
        avatar_href: "http://example.org/zzzzzz",
        description: "Eat pizza",
        status: "non_started"
      }
    ]
  }
}

I'm trying to avoid nasty metadata structures that are emerging in JSON hypermedia standards that would make this look like:

{
  href: '/lists/1',
  name: "Todo List",
  items: {
    href: '/lists/1203/items',
    links: {
      next: "/lists/1203/items?page=2"
    },
    collection: [
      {
        href: '/items/1',
        description: "Pick up pizza",
        status: "completed",
        blog_href: "http://example.org/xxxxx",
        avatar_href: "http://example.org/yyyyy"
      },
      {
        href: '/items/12',
        description: "Eat pizza",
        status: "non_started",
        blog_href: "http://example.org/qqqqqq",
        avatar_href: "http://example.org/zzzzzz"
      }
    ]
  }
}

When words like "collection" emerge within a data structure like JSON I feel like we're doing it wrong. I've also seen a number of JSON hypermedia standards preface keys with an _ to denote meta data (e.g. _href) which also feels like an anti-pattern.

Interesting, look what happens when my first example is implemented as Haml XML:

!!! xml
%list{href: '/lists/1'}
  %name Todo List
  %items{href: '/lists/1203/items'}
    %link{rel: "next", href: "/lists/1203/items?page=2"}
    %item{href: '/items/1'}
      %link{rel: "blog", href: "http://example.org/xxxxx"}
      %link{rel: "avatar", href: "http://example.org/yyyyy"}
      %description Pick up pizza
      %status completed
    %item{href: '/items/12'}
      %link{rel: "blog", href: "http://example.org/qqqqqq"}
      %link{rel: "avatar", href: "http://example.org/zzzzzz"}
      %description Eat pizza
      %status non_started

I notice a few problems:

  1. I need to think more about how a hypermedia client would figure out that the <items/> attribute contains a collection of <item/>'s
  2. The %link elements feel too generic and contrived for this example. They would make more sense if the links were attachments like %link{rel="attachment" href="pizza_receipt.pdf"}.

Interesting how the development community at large might be blowing up JSON into the complex monstrosity that XML was in the early 2000's.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment