Skip to content

Instantly share code, notes, and snippets.

@bradgessler
Last active December 29, 2015 00:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradgessler/7587671 to your computer and use it in GitHub Desktop.
Save bradgessler/7587671 to your computer and use it in GitHub Desktop.
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"
}
]
}
@mamund
Copy link

mamund commented Nov 21, 2013

interesting idea.

how would you describe things like HTML.IMG vs. HTML.A (embed vs. navigate) or HTML.FORM@method="post" (including arguments) in HON?

@bradgessler
Copy link
Author

@mamund HON wouldn't make the distinction between embed vs navigate. That would be left to the consumer of HON data. HON is only concerned about sending data over the wire with the same data structures as JSON while providing metadata facilities for certain keys.

Maybe I'm not understanding the question? What you describe seems like an HTML problem that HTML already solves.

@mamund
Copy link

mamund commented Nov 22, 2013

consider 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"
      href: "http://example.org/xxxxx",
      href: "http://example.org/yyyyy"
    },
    item(href: '/items/12'): {
      description: "Eat pizza",
      status: "non_started"
    }
  ]
}

one of those URLs is the related blog page (LO), the other is the user's avatar (LE). which is which? when i write a hypermedia client, i want to know that.

also, my client code wants to know what other transitions like search (LT) or edit (LI) or add (LN) exist. how can my client find that out? Collection+JSON and Siren do a good job of that today.

@bradgessler
Copy link
Author

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

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