Skip to content

Instantly share code, notes, and snippets.

@ericelliott
Last active December 10, 2015 03:28
Show Gist options
  • Save ericelliott/4374726 to your computer and use it in GitHub Desktop.
Save ericelliott/4374726 to your computer and use it in GitHub Desktop.
Collection+JSON .findItems()
{ "collection" :
{
"href" : "/touts/pending/",
"items": [
{
"href": "/touts/fk9abg",
"body": {
"uid": "fk9abg",
"text": "It's safe to say that this was the best moment today. LOL #KellyandMichael",
"parsed_text": {
"hashtags": [
{
"text": "#KellyandMichael",
"name": "KellyandMichael",
"indices": [
58,
74
],
"uid": "kellyandmichael",
"type": "hashtags"
}
],
"mentions": [],
"urls": []
},
"views_count": 1492,
"likes_count": 22,
"total_likes_count": 22,
"replies_count": 0,
"retouts_count": 6,
"recorded_at": "2012-12-20T22:14:13Z",
"created_at": "2012-12-20T22:14:13Z",
"privacy": "public",
"user": {
"username": "KellyandMichael",
"uid": "kellyandmichael",
"fullname": "LIVE! with Kelly and Michael",
"verified": true,
"location": "New York",
"bio": "The official “LIVE! with Kelly and Michael” Tout page! Be the first to know the latest from the show. Watch “LIVE! with Kelly and Michael” weekday mornings with Kelly Ripa and Michael Strahan.\r\n\r\n",
"friendly_name": "LIVE! with Kelly and Michael",
"touts_count": 544,
"followers_count": 33113,
"friends_count": 5,
"last_tout_recorded_at": "2012-12-25T16:18:24Z",
"created_at": "2012-03-27T16:32:02Z",
"avatar": {
"profile": {
"http_url": "http://avatars.tout.com/u/20b3d997063c8b8ad60b4aa63c8ffbee/profile/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"large": {
"http_url": "http://avatars.tout.com/u/20b3d997063c8b8ad60b4aa63c8ffbee/large/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"medium": {
"http_url": "http://avatars.tout.com/u/20b3d997063c8b8ad60b4aa63c8ffbee/medium/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"small": {
"http_url": "http://avatars.tout.com/u/20b3d997063c8b8ad60b4aa63c8ffbee/small/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
}
},
"following": false,
"followed_by": false
},
"image": {
"poster": {
"width": 640,
"height": 360,
"http_url": "http://thumbnails.tout.com/dry/db6ca28223acc087/poster-13.jpg"
},
"thumbnail": {
"width": 150,
"height": 84,
"http_url": "http://thumbnails.tout.com/dry/db6ca28223acc087/thumbs-13.jpg"
}
},
"video": {
"type": "native",
"duration": 16,
"mp4": {
"width": 640,
"height": 360,
"http_url": "http://videos.tout.com/dry/mp4/db6ca28223acc087.mp4"
}
},
"liked": false
}
},
{
"href": "/touts/nim3x1/",
"body": {
"uid": "nim3x1",
"text": "LOL everyone is soooooo excited #Backstage today! VIDEO:",
"parsed_text": {
"hashtags": [
{
"text": "#Backstage",
"name": "Backstage",
"indices": [
32,
42
],
"uid": "backstage",
"type": "hashtags"
}
],
"mentions": [
],
"urls": [
]
},
"views_count": 442,
"likes_count": 5,
"total_likes_count": 5,
"replies_count": 0,
"retouts_count": 0,
"recorded_at": "2012-12-20T14:01:11Z",
"created_at": "2012-12-20T14:03:22Z",
"privacy": "public",
"user": {
"username": "KellyandMichael",
"uid": "kellyandmichael",
"fullname": "LIVE! with Kelly and Michael",
"verified": true,
"location": "New York",
"bio": "The official \u201cLIVE! with Kelly and Michael\u201d Tout page! Be the first to know the latest from the show. Watch \u201cLIVE! with Kelly and Michael\u201d weekday mornings with Kelly Ripa and Michael Strahan.\r\n\r\n",
"friendly_name": "LIVE! with Kelly and Michael",
"touts_count": 542,
"followers_count": 32603,
"friends_count": 5,
"last_tout_recorded_at": "2012-12-20T22:14:13Z",
"created_at": "2012-03-27T16:32:02Z",
"avatar": {
"profile": {
"http_url": "http:\/\/avatars.tout.com\/u\/20b3d997063c8b8ad60b4aa63c8ffbee\/profile\/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"large": {
"http_url": "http:\/\/avatars.tout.com\/u\/20b3d997063c8b8ad60b4aa63c8ffbee\/large\/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"medium": {
"http_url": "http:\/\/avatars.tout.com\/u\/20b3d997063c8b8ad60b4aa63c8ffbee\/medium\/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
},
"small": {
"http_url": "http:\/\/avatars.tout.com\/u\/20b3d997063c8b8ad60b4aa63c8ffbee\/small\/LIVE_Kelly_and_Michael_best_graphic_psd_copy.jpg"
}
},
"following": false,
"followed_by": false
},
"image": {
"poster": {
"width": 568,
"height": 320,
"http_url": "http:\/\/thumbnails.tout.com\/dry\/ab6f39afb719e143\/poster-3.jpg"
},
"thumbnail": {
"width": 150,
"height": 84,
"http_url": "http:\/\/thumbnails.tout.com\/dry\/ab6f39afb719e143\/thumbs-3.jpg"
}
},
"video": {
"type": "native",
"duration": 16,
"mp4": {
"width": 568,
"height": 320,
"http_url": "http:\/\/videos.tout.com\/dry\/mp4\/ab6f39afb719e143.mp4"
}
},
"liked": false
}
}
]
}
}
findItems = function findItems(keyName, value) {
return this.items.filter(function (item) {
return item.data.filter(function (data) {
return data.name === keyName &&
data.value === value;
})[0];
});
}
@ericelliott
Copy link
Author

The Collection+JSON anonymous object link collection makes perfect sense. It's a good mix of flexibility and usability. However, the data array in the items collection is a different case. It requires nested iteration to retrieve data from the items collection.

Accessing the right data is a bit of a pain. For example, take a look at this .findItems() implementation:

findItems = function findItems(keyName, value) {
  return this.items.filter(function (item) {
    return item.data.filter(function (data) {
      return data.name === keyName &&
        data.value === value;
    })[0];
  });
};

This is fine for some use cases, but .findItems() will not perform well for large collections of large objects, because the data format forces two keyed lookups inside a nested loop.

Couple that with the fact that most people are accustomed to just getting an object with key/value pairs back from an API endpoint, and you've got a recipe for developer revolt. What most people really want for item data payloads is a key / value store with unbounded value types.

The Rotten Tomatoes API is one of the most cited production hypermedia API examples. Take a look at the way they do it:

http://developer.rottentomatoes.com/docs

It looks a lot like Collection+JSON, but gone are the cumbersome anonymous objects for all the data attributes. Instead, the item is an unrestricted JSON object. That said, it isn't perfect.

What I love about the Collection+JSON representation is that (unlike the Rotten Tomatoes API), you can associate metadata (including links) without mixing a reserved key into the data payload. The idea of associating metadata as a sibling of the data payload object works much more like the head / body separation in HTML. In my opinion, it's an elegant approach.

I propose a middle ground -- an alternative to the Collection+JSON data array - a sibling body attribute that has an unrestricted value. The server can deliver any type of valid JSON object as the payload in body.

It might look something like the body.json, above.

The new .findItems becomes:

findItems = function findItems(keyName, value) {
  return this.items.filter(function (item) {
    return (item.body) ?
      item.body[keyName] === value :
      false;
  });
};

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