SlideShare a Scribd company logo
1 of 40
Crafting Evolvable API
Responses
Who am I?
• Twitter: @darrel_miller
• http://www.bizcoder.com/
Solve API Problems Fast
Our Journey Today
• Focus on API responses
• Versioning is painful
• Why we think we need it?
• How can we avoid it?
• What if you can’t?
Objects over the wire
We have been here before
• CORBA, DCOM
• SOAP, WSDL
• DTOs
• JSON
The ASP.NET Web API Project Template
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get() { return new string[] { "value1", "value2" };}
// GET api/values/5
public string Get(int id) { return "value"; }
// POST api/values
public void Post([FromBody]string value) { }
// PUT api/values/5
public void Put(int id, [FromBody]string value) { }
// DELETE api/values/5
public void Delete(int id) { }
}
The ASP.NET Web API Starter Tutorial
public class ProductsController : ApiController
{
//…
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
ServiceStack
public class ReqstarsService : Service
{
public List<Reqstar> Get(AllReqstars request)
{
return Db.Select<Reqstar>();
}
}
NancyFX
public class SampleModule : Nancy.NancyModule
{
public SampleModule()
{
Get["/"] = _ => "Hello World!";
}
}
Python Flask
@app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
Rails
# Returns the resource from the created instance variable
# @return [Object]
def get_resource
instance_variable_get("@#{resource_name}")
end
But, what’s the problem?
Which objects to map?
• Domain objects
• How do we hide content we don’t want to expose?
• How do we create different views of data?
• Changes to domain model cause changes to API
• DTOs
• whole lot of busy work
• Only indirect control over serialization process
Automatic Serialization
• All the properties
• Missing values, unrecognized properties
• Non standard data types: datetime, timespan
• Does null mean unspecified, or explicitly null?
• Empty collection or no collection
• Capitalization
• Links
• Cycles
• Changes to behavior in the frameworks
• Security Risks
The whole app is useless
because the API added a new
preference
APIs Break because Serialization Libraries Change/Fix things
Take back control
Use a DOM to build your document
dynamic jspeaker = new JObject();
jspeaker.name = speakerInfo.Name;
jspeaker.bio = speakerInfo.Bio;
dynamic links = new JObject();
dynamic iconLink = new JObject();
iconLink.href = speakerInfo.ImageUrl;
links.icon = iconLink;
dynamic sessionsLink = new JObject();
sessionsLink.href = SessionsLinkHelper.CreateLink(request, speakerInfo).Target;
links[LinkHelper.GetLinkRelationTypeName<SessionsLink>()] = sessionsLink;
jspeaker["_links"] = links;
return new DynamicHalContent(jspeaker);
What to do with your new found freedom?
Resources and Representations
/api/order/34
/api/order/35
/api/order/35/invoice.html
application/json
application/ld+json
/api/order/35/invoice.pdf
application/json
application/ld+json
application/pdf
text/html
/api/PrintQueue
/api/CurrentWeather
/api/LeaderBoard
Anatomy of an HTTP representation
200 OK HTTP/1.1
Server: Microsoft-HTTPAPI/2.0
Content-Length: 44
Content-Type: text/plain
Acme-perf-database-cost: 120ms
The quick brown fox jumped over the lazy dog
Let’s build some payloads
{
"description" :"There is a hole in my bucket"
}
The smallest thing that is actionable
{
"description" :"There is a hole in my bucket",
"steps_to_reproduce" : "Pour water in bucket. Lift bucket off
ground. Look for water dripping",
"date_reported": "2012-04-21T18:25:43-05:00"
}
Just enough data to solve the problem
{
"description" :"The font is too big",
"application_name" : "Wordament",
"application_version" : "1.2.0.2392",
"environment_osversion" : "NT4.0",
"environment_memory_free" : "100 MB",
"environment_diskspace_free" : "1.5 GB",
"reported_by_user" : “Bob Bing”
}
Why do they need that data?
{
"description" :"The font is too big",
"application_name" : "Wordament",
"application_version" : "1.2.0.2392",
"environment" : { "osversion" : "NT4.0",
"memory_free" : "100 MB",
"diskspace_free" : "1.5 GB"
}
}
Attribute Groups
{
"description" :"The font is too big",
"history" : [
{"status" : "reported", "date" :"2014-02-01"},
{"status" : "triaged", "date" :"2014-02-04"},
{"status" : "assigned", "date" :"2014-02-12"},
{"status" : "resolved", "date" :"2014-02-19"},
]
}
Attribute Groups for multiple instances
{
"description" :"The font is too big",
"reported_by_user" : { "name" : "Bob Bing",
"email" : "bob@acme.com",
"twitter" : "@bobbing",
"date_hired" : "2001-01-21"
}
}
Attribute Groups for related data
{
"description" :"The font is too big",
"reported_by_user_url" : "http://api.acme.com/users/75"
}
Linking related data
{
"description" :"The font is too big",
“links" : [
{ "href" :"http://api.acme.com/users/75", "rel": "reportedbyuser" },
{ "href" :"http://api.acme.com/users/24", "rel": "assignedtouser" }
]
}
Multiple Links
{
"issues" : [
{
"description" :"There is a hole in my bucket"
}
]
}
Beware of structural changes
{
"issue" :
{
"description" :"There is a hole in my bucket"
}
}
Item in a Array
Item as a Property
Naming Your Conventions
• Empty arrays
• Nulls
• Single item as array or object
• Camel case, snake case
• Vocabulary
• Protocols
Media Type Scope
application/json
application/vnd.acme.issue+json
application/issue+json
Too broad
Too narrow
Ideal
application/hal+json Partial
application/vnd.acmeapi+json Compromise
Vocabularies : Profiles, Namespaces, Schemas, Ontologies
Learn from others
application/hal+json
application/ld+json
application/vnd.mason+json
application/vnd.siren+json
application/vnd.amundsen-uber+json
application/vnd.github.v3+json
application/vnd.heroku+json
application/vnd.api+json
application/atom+xml
application/voicexml+xml
application/vnd.collection+json
application/activity+json
application/http-problem
application/json-home
Generic Hypermedia API Specific Task Specific
{
"description" :"The font is too big",
"_embedded" : {
"reportedByUser" : {
"name" : "Bob Bing",
"email" : "bob@acme.com",
"_links" : { "self" : {"href" :"http://api.acme.com/users/75"}}
}
}
Meet application/hal+json
{
"collection": { "links": [],
"items": [
{
"data": [
{ "name": "Title",
"value": "rntttLearning from Noda Time: a case study in API design and open source (good, bad and ugly)rntt“ },
{ "name": "Timeslot",
"value": "04 December 2013 16:20 - 17:20“ },
{ "name": "Speaker",
"value": "Jon Skeet“ }
],
"links": [ {
"href": "http://conference.hypermediaapi.com/speaker/6",
"rel": "http://tavis.net/rels/speaker" }, {
"href": "http://conference.hypermediaapi.com/session/133/topics",
"rel": "http://tavis.net/rels/topics" }
],
"href": "http://conference.hypermediaapi.com/session/133"
}
],
"query": [], "template": { "data": [] },
"version": "1.0"
}
}
Meet application/vnd.collection+json
Version as a Last Resort
• Version the payload
• HTML DOCTYPE, Collection+Json
• Version the resource
• /api/documents/invoice.v2/758
• Version the media type
• application/vnd.github.v3+json
• Version the API
• /api/v2/documents/invoice/758
Wrap up
• Understand the limitations of “objects over the wire”
• Consider taking back control of your representations
• Think in terms of messages, instead of objects
• Build software that is designed to survive change
• Believe that versioning is an admission of failure
Image Credits
• Package - https://flic.kr/p/3mrNyn
• Freedom - https://flic.kr/p/4vwRDw
• Treasure map - https://flic.kr/p/7jDJwi
• Handshake - https://flic.kr/p/nbAu8Y
• Telephone - https://flic.kr/p/7Q8bMd
• Blindfolded Typing - https://flic.kr/p/53Q3JE
• Magic Trick - https://flic.kr/p/7T8zk5
• Donut machine - https://flic.kr/p/anncxf
• GT-R Steering Wheel - https://flic.kr/p/fDUSDk
• Anatomy - https://flic.kr/p/6bfUZn
• Shapes - https://flic.kr/p/3aKUAq
• Payloaders - https://flic.kr/p/dTU9sN
• Birds on a Wire - https://flic.kr/p/4YdfK

More Related Content

What's hot

Scaling your Android App With Modularization
Scaling your Android App With ModularizationScaling your Android App With Modularization
Scaling your Android App With ModularizationBen Schwab
 
Intoduction to Play Framework
Intoduction to Play FrameworkIntoduction to Play Framework
Intoduction to Play FrameworkKnoldus Inc.
 
Java EE changes design pattern implementation: JavaDays Kiev 2015
Java EE changes design pattern implementation: JavaDays Kiev 2015Java EE changes design pattern implementation: JavaDays Kiev 2015
Java EE changes design pattern implementation: JavaDays Kiev 2015Alex Theedom
 
Access to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAccess to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAtlassian
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteIsaacSchlueter
 
Module 3: Working with the DOM and jQuery
Module 3: Working with the DOM and jQueryModule 3: Working with the DOM and jQuery
Module 3: Working with the DOM and jQueryDaniel McGhan
 
Supercharge Your Pages - New Ways to Extend the Confluence Editor
Supercharge Your Pages - New Ways to Extend the Confluence EditorSupercharge Your Pages - New Ways to Extend the Confluence Editor
Supercharge Your Pages - New Ways to Extend the Confluence EditorAtlassian
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with RailsBasayel Said
 
Open Source Mobile Backend on Cassandra
Open Source Mobile Backend on CassandraOpen Source Mobile Backend on Cassandra
Open Source Mobile Backend on CassandraEd Anuff
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native WorkshopIgnacio Martín
 
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...CA API Management
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravelwajrcs
 
Building Better Web APIs with Rails
Building Better Web APIs with RailsBuilding Better Web APIs with Rails
Building Better Web APIs with RailsAll Things Open
 
Usergrid Overview
Usergrid OverviewUsergrid Overview
Usergrid Overviewusergrid
 
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIO
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIOJumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIO
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIOJosh Cypher
 
React Native: Introduction
React Native: IntroductionReact Native: Introduction
React Native: IntroductionInnerFood
 
Building Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET CoreBuilding Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET CoreStormpath
 

What's hot (20)

jQuery for web development
jQuery for web developmentjQuery for web development
jQuery for web development
 
Scaling your Android App With Modularization
Scaling your Android App With ModularizationScaling your Android App With Modularization
Scaling your Android App With Modularization
 
Intoduction to Play Framework
Intoduction to Play FrameworkIntoduction to Play Framework
Intoduction to Play Framework
 
Java EE changes design pattern implementation: JavaDays Kiev 2015
Java EE changes design pattern implementation: JavaDays Kiev 2015Java EE changes design pattern implementation: JavaDays Kiev 2015
Java EE changes design pattern implementation: JavaDays Kiev 2015
 
Access to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAccess to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIs
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoComplete
 
Module 3: Working with the DOM and jQuery
Module 3: Working with the DOM and jQueryModule 3: Working with the DOM and jQuery
Module 3: Working with the DOM and jQuery
 
Supercharge Your Pages - New Ways to Extend the Confluence Editor
Supercharge Your Pages - New Ways to Extend the Confluence EditorSupercharge Your Pages - New Ways to Extend the Confluence Editor
Supercharge Your Pages - New Ways to Extend the Confluence Editor
 
Appengine Nljug
Appengine NljugAppengine Nljug
Appengine Nljug
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with Rails
 
Open Source Mobile Backend on Cassandra
Open Source Mobile Backend on CassandraOpen Source Mobile Backend on Cassandra
Open Source Mobile Backend on Cassandra
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
 
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...
API Design Methodology - Mike Amundsen, Director of API Architecture, API Aca...
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
Building Better Web APIs with Rails
Building Better Web APIs with RailsBuilding Better Web APIs with Rails
Building Better Web APIs with Rails
 
Usergrid Overview
Usergrid OverviewUsergrid Overview
Usergrid Overview
 
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIO
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIOJumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIO
Jumpstarting Testing In Your Organization with Selenium, Cucumber, & WebdriverIO
 
React Native: Introduction
React Native: IntroductionReact Native: Introduction
React Native: Introduction
 
IoC with PHP
IoC with PHPIoC with PHP
IoC with PHP
 
Building Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET CoreBuilding Beautiful REST APIs with ASP.NET Core
Building Beautiful REST APIs with ASP.NET Core
 

Viewers also liked

Viewers also liked (8)

Circulatory system
Circulatory systemCirculatory system
Circulatory system
 
Respiratory system
Respiratory systemRespiratory system
Respiratory system
 
Excretory system
Excretory systemExcretory system
Excretory system
 
Unit 4
Unit 4Unit 4
Unit 4
 
Unit 4. nervous system
Unit 4. nervous systemUnit 4. nervous system
Unit 4. nervous system
 
Digestive system
Digestive systemDigestive system
Digestive system
 
Unit 4 science. our systems
Unit 4 science. our systemsUnit 4 science. our systems
Unit 4 science. our systems
 
FICHAS INTELIGENCIA 4º
FICHAS INTELIGENCIA 4º  FICHAS INTELIGENCIA 4º
FICHAS INTELIGENCIA 4º
 

Similar to Crafting Evolvable API Responses

Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responsesdarrelmiller71
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Exploring an API with Blocks
Exploring an API with BlocksExploring an API with Blocks
Exploring an API with BlocksPronovix
 
API Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationAPI Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 
Nordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationNordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 
From Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) AgainFrom Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) Againjonknapp
 
Real World Asp.Net WebApi Applications
Real World Asp.Net WebApi ApplicationsReal World Asp.Net WebApi Applications
Real World Asp.Net WebApi ApplicationsEffie Arditi
 
Node.js Patterns for Discerning Developers
Node.js Patterns for Discerning DevelopersNode.js Patterns for Discerning Developers
Node.js Patterns for Discerning Developerscacois
 
apidays LIVE LONDON - Exploring an API with Blocks by Larry Kluger
apidays LIVE LONDON - Exploring an API with Blocks by Larry Klugerapidays LIVE LONDON - Exploring an API with Blocks by Larry Kluger
apidays LIVE LONDON - Exploring an API with Blocks by Larry Klugerapidays
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformAntonio Peric-Mazar
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterHaehnchen
 
apidays LIVE Paris - Exploring an API with Blocks by Larry Kluger
apidays LIVE Paris - Exploring an API with Blocks by Larry Klugerapidays LIVE Paris - Exploring an API with Blocks by Larry Kluger
apidays LIVE Paris - Exploring an API with Blocks by Larry Klugerapidays
 
Operational API design anti-patterns (Jason Harmon)
Operational API design anti-patterns (Jason Harmon)Operational API design anti-patterns (Jason Harmon)
Operational API design anti-patterns (Jason Harmon)Nordic APIs
 
Intro To Spring Python
Intro To Spring PythonIntro To Spring Python
Intro To Spring Pythongturnquist
 
Programming With Amazon, Google, And E Bay
Programming With Amazon, Google, And E BayProgramming With Amazon, Google, And E Bay
Programming With Amazon, Google, And E BayPhi Jack
 
API Days Australia - Automatic Testing of (RESTful) API Documentation
API Days Australia  - Automatic Testing of (RESTful) API DocumentationAPI Days Australia  - Automatic Testing of (RESTful) API Documentation
API Days Australia - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 

Similar to Crafting Evolvable API Responses (20)

Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
 
Real World MVC
Real World MVCReal World MVC
Real World MVC
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Exploring an API with Blocks
Exploring an API with BlocksExploring an API with Blocks
Exploring an API with Blocks
 
API Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationAPI Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API Documentation
 
Nordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationNordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API Documentation
 
From Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) AgainFrom Backbone to Ember and Back(bone) Again
From Backbone to Ember and Back(bone) Again
 
2012: ql.io and Node.js
2012: ql.io and Node.js2012: ql.io and Node.js
2012: ql.io and Node.js
 
Real World Asp.Net WebApi Applications
Real World Asp.Net WebApi ApplicationsReal World Asp.Net WebApi Applications
Real World Asp.Net WebApi Applications
 
Andrei shakirin rest_cxf
Andrei shakirin rest_cxfAndrei shakirin rest_cxf
Andrei shakirin rest_cxf
 
Node.js Patterns for Discerning Developers
Node.js Patterns for Discerning DevelopersNode.js Patterns for Discerning Developers
Node.js Patterns for Discerning Developers
 
apidays LIVE LONDON - Exploring an API with Blocks by Larry Kluger
apidays LIVE LONDON - Exploring an API with Blocks by Larry Klugerapidays LIVE LONDON - Exploring an API with Blocks by Larry Kluger
apidays LIVE LONDON - Exploring an API with Blocks by Larry Kluger
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
apidays LIVE Paris - Exploring an API with Blocks by Larry Kluger
apidays LIVE Paris - Exploring an API with Blocks by Larry Klugerapidays LIVE Paris - Exploring an API with Blocks by Larry Kluger
apidays LIVE Paris - Exploring an API with Blocks by Larry Kluger
 
Operational API design anti-patterns (Jason Harmon)
Operational API design anti-patterns (Jason Harmon)Operational API design anti-patterns (Jason Harmon)
Operational API design anti-patterns (Jason Harmon)
 
Gohan
GohanGohan
Gohan
 
Intro To Spring Python
Intro To Spring PythonIntro To Spring Python
Intro To Spring Python
 
Programming With Amazon, Google, And E Bay
Programming With Amazon, Google, And E BayProgramming With Amazon, Google, And E Bay
Programming With Amazon, Google, And E Bay
 
API Days Australia - Automatic Testing of (RESTful) API Documentation
API Days Australia  - Automatic Testing of (RESTful) API DocumentationAPI Days Australia  - Automatic Testing of (RESTful) API Documentation
API Days Australia - Automatic Testing of (RESTful) API Documentation
 

Recently uploaded

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 

Recently uploaded (20)

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 

Crafting Evolvable API Responses

  • 2. Who am I? • Twitter: @darrel_miller • http://www.bizcoder.com/ Solve API Problems Fast
  • 3. Our Journey Today • Focus on API responses • Versioning is painful • Why we think we need it? • How can we avoid it? • What if you can’t?
  • 5. We have been here before • CORBA, DCOM • SOAP, WSDL • DTOs • JSON
  • 6. The ASP.NET Web API Project Template public class ValuesController : ApiController { // GET api/values public IEnumerable<string> Get() { return new string[] { "value1", "value2" };} // GET api/values/5 public string Get(int id) { return "value"; } // POST api/values public void Post([FromBody]string value) { } // PUT api/values/5 public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 public void Delete(int id) { } }
  • 7. The ASP.NET Web API Starter Tutorial public class ProductsController : ApiController { //… public IEnumerable<Product> GetAllProducts() { return products; } public IHttpActionResult GetProduct(int id) { var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { return NotFound(); } return Ok(product); } } http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
  • 8. ServiceStack public class ReqstarsService : Service { public List<Reqstar> Get(AllReqstars request) { return Db.Select<Reqstar>(); } }
  • 9. NancyFX public class SampleModule : Nancy.NancyModule { public SampleModule() { Get["/"] = _ => "Hello World!"; } }
  • 10. Python Flask @app.route('/todo/api/v1.0/tasks', methods=['GET']) def get_tasks(): return jsonify({'tasks': tasks})
  • 11. Rails # Returns the resource from the created instance variable # @return [Object] def get_resource instance_variable_get("@#{resource_name}") end
  • 12. But, what’s the problem?
  • 13. Which objects to map? • Domain objects • How do we hide content we don’t want to expose? • How do we create different views of data? • Changes to domain model cause changes to API • DTOs • whole lot of busy work • Only indirect control over serialization process
  • 14. Automatic Serialization • All the properties • Missing values, unrecognized properties • Non standard data types: datetime, timespan • Does null mean unspecified, or explicitly null? • Empty collection or no collection • Capitalization • Links • Cycles • Changes to behavior in the frameworks • Security Risks
  • 15. The whole app is useless because the API added a new preference
  • 16. APIs Break because Serialization Libraries Change/Fix things
  • 18. Use a DOM to build your document dynamic jspeaker = new JObject(); jspeaker.name = speakerInfo.Name; jspeaker.bio = speakerInfo.Bio; dynamic links = new JObject(); dynamic iconLink = new JObject(); iconLink.href = speakerInfo.ImageUrl; links.icon = iconLink; dynamic sessionsLink = new JObject(); sessionsLink.href = SessionsLinkHelper.CreateLink(request, speakerInfo).Target; links[LinkHelper.GetLinkRelationTypeName<SessionsLink>()] = sessionsLink; jspeaker["_links"] = links; return new DynamicHalContent(jspeaker);
  • 19. What to do with your new found freedom?
  • 21. Anatomy of an HTTP representation 200 OK HTTP/1.1 Server: Microsoft-HTTPAPI/2.0 Content-Length: 44 Content-Type: text/plain Acme-perf-database-cost: 120ms The quick brown fox jumped over the lazy dog
  • 22. Let’s build some payloads
  • 23. { "description" :"There is a hole in my bucket" } The smallest thing that is actionable
  • 24. { "description" :"There is a hole in my bucket", "steps_to_reproduce" : "Pour water in bucket. Lift bucket off ground. Look for water dripping", "date_reported": "2012-04-21T18:25:43-05:00" } Just enough data to solve the problem
  • 25. { "description" :"The font is too big", "application_name" : "Wordament", "application_version" : "1.2.0.2392", "environment_osversion" : "NT4.0", "environment_memory_free" : "100 MB", "environment_diskspace_free" : "1.5 GB", "reported_by_user" : “Bob Bing” } Why do they need that data?
  • 26. { "description" :"The font is too big", "application_name" : "Wordament", "application_version" : "1.2.0.2392", "environment" : { "osversion" : "NT4.0", "memory_free" : "100 MB", "diskspace_free" : "1.5 GB" } } Attribute Groups
  • 27. { "description" :"The font is too big", "history" : [ {"status" : "reported", "date" :"2014-02-01"}, {"status" : "triaged", "date" :"2014-02-04"}, {"status" : "assigned", "date" :"2014-02-12"}, {"status" : "resolved", "date" :"2014-02-19"}, ] } Attribute Groups for multiple instances
  • 28. { "description" :"The font is too big", "reported_by_user" : { "name" : "Bob Bing", "email" : "bob@acme.com", "twitter" : "@bobbing", "date_hired" : "2001-01-21" } } Attribute Groups for related data
  • 29. { "description" :"The font is too big", "reported_by_user_url" : "http://api.acme.com/users/75" } Linking related data
  • 30. { "description" :"The font is too big", “links" : [ { "href" :"http://api.acme.com/users/75", "rel": "reportedbyuser" }, { "href" :"http://api.acme.com/users/24", "rel": "assignedtouser" } ] } Multiple Links
  • 31. { "issues" : [ { "description" :"There is a hole in my bucket" } ] } Beware of structural changes { "issue" : { "description" :"There is a hole in my bucket" } } Item in a Array Item as a Property
  • 32. Naming Your Conventions • Empty arrays • Nulls • Single item as array or object • Camel case, snake case • Vocabulary • Protocols
  • 33. Media Type Scope application/json application/vnd.acme.issue+json application/issue+json Too broad Too narrow Ideal application/hal+json Partial application/vnd.acmeapi+json Compromise Vocabularies : Profiles, Namespaces, Schemas, Ontologies
  • 35. { "description" :"The font is too big", "_embedded" : { "reportedByUser" : { "name" : "Bob Bing", "email" : "bob@acme.com", "_links" : { "self" : {"href" :"http://api.acme.com/users/75"}} } } Meet application/hal+json
  • 36. { "collection": { "links": [], "items": [ { "data": [ { "name": "Title", "value": "rntttLearning from Noda Time: a case study in API design and open source (good, bad and ugly)rntt“ }, { "name": "Timeslot", "value": "04 December 2013 16:20 - 17:20“ }, { "name": "Speaker", "value": "Jon Skeet“ } ], "links": [ { "href": "http://conference.hypermediaapi.com/speaker/6", "rel": "http://tavis.net/rels/speaker" }, { "href": "http://conference.hypermediaapi.com/session/133/topics", "rel": "http://tavis.net/rels/topics" } ], "href": "http://conference.hypermediaapi.com/session/133" } ], "query": [], "template": { "data": [] }, "version": "1.0" } } Meet application/vnd.collection+json
  • 37. Version as a Last Resort • Version the payload • HTML DOCTYPE, Collection+Json • Version the resource • /api/documents/invoice.v2/758 • Version the media type • application/vnd.github.v3+json • Version the API • /api/v2/documents/invoice/758
  • 38. Wrap up • Understand the limitations of “objects over the wire” • Consider taking back control of your representations • Think in terms of messages, instead of objects • Build software that is designed to survive change • Believe that versioning is an admission of failure
  • 39.
  • 40. Image Credits • Package - https://flic.kr/p/3mrNyn • Freedom - https://flic.kr/p/4vwRDw • Treasure map - https://flic.kr/p/7jDJwi • Handshake - https://flic.kr/p/nbAu8Y • Telephone - https://flic.kr/p/7Q8bMd • Blindfolded Typing - https://flic.kr/p/53Q3JE • Magic Trick - https://flic.kr/p/7T8zk5 • Donut machine - https://flic.kr/p/anncxf • GT-R Steering Wheel - https://flic.kr/p/fDUSDk • Anatomy - https://flic.kr/p/6bfUZn • Shapes - https://flic.kr/p/3aKUAq • Payloaders - https://flic.kr/p/dTU9sN • Birds on a Wire - https://flic.kr/p/4YdfK

Editor's Notes

  1. - Developer advocate for Runscope. - Cloud based solutions for API performance monitoring Microsoft MVP Book
  2. Two parts to API design, resource identification and representation design designing representations aka HTTP response. - Versioning sucks So many ways to do it Starting to hear the message, don’t version Roy says middle finger Layer7 say don’t. The problem is we all make mistakes. - Why do we think we need it
  3. One reason we think we need versioning is because we do Objects over the wire Pass object graph Infrastructure converts it Hope the client understands it Pre-arranged agreement between client/server The details are key to avoiding versioning. But Web APIs are not the same as local APIs Objects over the wire. The idea is that you construct some kind of object graph in your favourite language in your web application, that contains the data that you want to deliver to the clients. And then you pass that object graph to some piece of infrastructure code that converts it into a wire format that hopefully will be consumable by the client. The challenge is, for this to work, there has to be some kind of pre-arranged agreement between sender and receiver. The details of that agreement are the key to avoiding versioning.
  4. - Trying to do this since the mid 1990’s CORBA, DCOM - When the web won, SOAP was invented simplified to DTOs - REST was rediscovered and redefined to use JSON to send objects over the wire JSON has helped. It makes the easy stuff really easy. But the more work we do in JSON the more we are starting to see the re-invention of the complexity. JSON-Schema, JSON Pointer, JSON Path, patch formats, namespacing. Fallacy of REST has no contracts. We are just pretending they are there, but they are implicit and unwritten. So what does “objects over the wire” look like in code, in the current incarnation. We have been trying to do this since the mid 1990’s. CORBA, DCOM were attempts to allow access to remote objects. When it was recognized that the web has won, SOAP was invented to try and do Objects over the wire on HTTP Some smart people realized that “objects over the wire” was never really going to succeed so they simplified to DTOs over the wire. Types over the wire, but sharing types creates coupling. SOAP used a similar concept but called them data contracts Only works if you have tight control over both sides of the wire.
  5. - The default behavior is to return CLR types let the framework decide how to convert it to representation on the wire What does Ienumerable<string> look like on the wire? Does every platform do it the same way? What does string look like on the wire? JSON spec has changed recently for simple values. POSTing string. So many StackOverflow questions on posting string of XML that doesn’t work. The worlds simplest API and multiple interoperability issues.
  6. In this example we move from returning a native CLR data type to a custom object. Product Note IHTTPActionResult Starts to break down when the information we are trying to send is not in the payload Returning a object limits how we can craft the response. But this is not just Microsoft doing silly things
  7. What are the odds that List<Reqstars> creates the same wire representation as List<Reqstars> in Web API Returning objects is hiding a critical information needed to ensure interoperability
  8. Even the really cool frameworks. I wonder what this will look like on the wire. It is a very common pattern. Every framework provider will tell you, “oh but you can customize the response if you want” …but that’s not where they lead you.
  9. It is also not a problem that is limited to the .net space. This python example is slightly better, because at least we know it is going to be sent as a JSON representation and the mapping from objects to JSON is fairly straight forward
  10. And just as one last example, rails does the same thing.
  11. So what, you say… most of those are minor implementation details. What’s the fundamental problem with objects over the wire?
  12. Even with DTOs, you only have indirect control over the serialization process
  13. If you address supports suite no you are going to get it whether there is a value or not. Sending data, what does it expect? Mandrill How do you format dates? iJson was a new standard developed to help interoperability In a geneology app, if Date of death is null, are we missing that data or is he just not dead yet? How you handle links in your server implementation is your business, how you format them on the wire is everyone’s business .Net objects don’t follow capitalization rules of JSON. What about word separation? Cycles can cause some serializers to die randomly. The great YAML fiasco When dealing with Automatic Serialization there are so many unknowns Being aware of what are the rules of your representations is absolutely critical. When you know it is a rule, you start to think about the long term effects and the cross platform concerns. When you are “just serializing your objects as JSON” you get a false sense of security.
  14. This is what happens when you are not clear about your contract.
  15. The poor guys writing the serializers. They break people when they fix things.
  16. What’s a DOM…. - Here is just one example of using the JSON.NET Jobject and dynamic. - There are many ways to do this. - helper methods allow you to establish conventions in your representation formats. - Instead of domain objects to DTOs, - Do domain objects/linq projections to DOM. - You define your own conventions instead of a serializer doing it for you. And maybe you don’t even have to define your own conventions, Maybe the conventions of an existing media type meet your needs
  17. The problem with not using serializers, now you have the problem of having think about how to structure your responses. So, let’s start with some fundamentals.
  18. Clear up confusion around terms. Mapping Resources to entities can be limiting to your design. A different URI should almost always be a different resource. Ideally if you want two URLs for the same resource then one should redirect to the other. Prevents cache pollution A Resource can have multiple representations, or just a single one. There is nothing wrong with creating distinct resources for available formats Resources can be completely dynamic concepts
  19. You can change that reason phrase… Headers are metadata about the response Performance – Headers can be processed and interpreted without having to interpret the entire request body. Cross cutting concerns Timing – Headers arrive first and can actually be used to abort the reception of the body, or prepare for the body, whilst downloading bytes Naming – don’t use x-, do use company- for custom headers Content - Links, json, Unicode? In the future http/2 will support header compression
  20. Often at the root of an API. Another example : Atom service document
  21. Building an Issue Tracking System Really simple minimal documents make it really easy to get started
  22. - Optional attributes can be added to the root object - Consider the use-case, not the server object model. - What would a serializer do? - Objects include everything. Guide client devs down the right path - You can always add, it’s much hard to take away. - There are reasons to group attributes, until you have a reason, probably not worth it. Structural changes are tricky. - Clients shouldn’t depend on order - Name it based on most natural conventions for the format
  23. How much semantics does the client really need? Is it going to do calcs on the memory free? Consider cultural issues, like formatting, language. Should a date be pretty formatted and localized? Should an address be concatenated or separate fields Should a name be two fields, or formatted firstname + lastname or last name comma first name
  24. Grouping together can have a variety of advantages saved a few bytes potentially more human readable allows definition of mandatory fields within a group, without the group itself being mandatory - group becomes a candidate for linking instead of embedding. It might map to an object, it might not.
  25. Groups are useful for supporting multiple instances of a set of data.
  26. Embed related data to reduce round trips When updating an issue, we would not update the contents of the reportedByUser. - Related information can also be included by providing a link. - Consider volatility and reusability of data. - beware of embedding short lived data inside long lived data.
  27. // Links can be very handy for pointing at information that changes rarely and can easily be cached locally. // There are many ways of representing links. Sometimes a link is presented as an object.
  28. Multiple objects can be displayed like this…
  29. Making a your concept a property allows for a issue.v2, …or allows for defining a media type that can hold many different concepts Sometimes you might want to make something a collection, even though today there is only one. Don’t make the root of your JSON object an array (must Ignore policy)
  30. “Media Type” is the name you give to your conventions Content-Type is the header to identify conventions to the client There is a lot of nitty gritty details to think about when defining a media type from scratch Better to layer new types on old ones. Profile is an attempt to separate the efforts.
  31. Distinction between what is here and what is elsewhere
  32. A list of things