In a modern web app, the application server implements a Web API that provides service to the front-end JavaScript code.
A Web API is a defined set of HTTP request messages along with a definition of the structure of response messages, usually expressed in JSON format (from Wikipedia).
A Web API provides service to clients through several endpoints. Each endpoint is named with an URL, e.g. http://example.com/products
. A client uses an appropriate HTTP verb to invoke the endpoint. There are a few common paradigms to design Web APIs and structure the endpoints. We’ll discuss two, namely REST and RPC, in the next two sections. We’ll use REST style in the examples here. However, the focus on this section is the payload in requests and responses.
The two most popular payload formats in Web APIs are URL-encoded and JSON. URL encoded payloads are key-value pairs, and are only suitable for simple values. JSON is more flexible in representing data structure.
URL-encoded | JSON | |
---|---|---|
Structure | key value pairs | similar to JavaScript objects |
Content type | application/x-www-form-urlencoded |
application/json |
In GET requests | as query of the URL | no |
In other requests (POST, PUT, etc) | in body | in body |
In responses | in body | in body |
‘URL-encoded’ was one of the original encoding in the Web to encode form data that a <form>
submits to a server. (We’ve discussed this in Chapter 1.) You can use URL-encoded in all kinds of requests and responses.
For example, below is a simple (RPC style) request to get information about product with id=5
.
GET /products.info?id=5 HTTP/1.1
Host: example.com
Notice that GET requests cannot have message body. Therefore, the URL-encoded payload must be packed in the URL.
The response for the above request could be the following.
HTTP/1.1 200 Ok
Content-type: application/x-www-form-urlencoded
Content-length: 79
id=5&productName=Coke+candy&category=Confections&unitPrice=10.5&unitsInStock=20
URL-encoded payload are also common as body of other kinds of requests (e.g. POST
, PUT
). Below is a sample (RPC style) request to create a new product.
POST /products.create HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 53
productName=Great+new+chocolate&category=Confections&unitPrice=20&unitsInStock=100
The JSON data format is a textual language-agnostic data exchange format. JSON is supported by many popular languages, including Java, Python, and, of course, JavaScript.
Below is a sample response message that returns information about the product with id=5
.
HTTP/1.1 200 Ok
Content-type: application/json
Content-length: 116
{
"id": 5,
"productName": "Coke candy",
"category": "Confections",
"unitPrice": 10.5,
"unitsInStock": 20
}
The syntax of JSON is similar to JavaScript object, array, numbers, string and boolean. But there are several differences.
"correct"
, not 'incorrect'
.{"name": "peter", "age": 20}
, not {name: "peter", 'age': 20}
[1,2,3]
.true
, false
, null
) are supported, but JSON data cannot include functions./* like this */
are not allowed in JSON.Although simple values like 123
, "json sample"
, true
are valid JSON data, in many Web APIs, the returned values in responses are object-enclosed. In other words, the root value in the JSON data is an object. Below are two possible designs for returning data about two products in JSON, e.g. in response to a search request. (We omit some fields about products for brevity.) The first design returns the items directly in an array.
HTTP/1.1 200 Ok
Content-type: application/json
Content-length: 131
[
{ "id": 5, "productName": "Coke candy", "unitPrice": 10.5 },
{ "id": 6, "productName": "Chocolate bar", "unitPrice": 25.0 }
]
The second design encloses the data in an object. Usually, the items are described under a property of the object, and there is another property to provide the number of items (e.g. count
).
HTTP/1.1 200 Ok
Content-type: application/json
Content-length: 166
{
"count": 2,
"items": [
{ "id": 5, "productName": "Coke candy", "unitPrice": 10.5 },
{ "id": 6, "productName": "Chocolate bar", "unitPrice": 25.0 }
]
}
GET
requests cannot take message body. Because JSON payload is usually large and may exceed the maximum allowable length of URL, we do not use JSON payload in GET
requests.
On the other hand, JSON payload can appear in the message body of non-GET requests (e.g. POST
, PUT
, DELETE
)
For example, to create a product, the client may send the following (RPC style) request.
POST /products.create HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 104
{
"productName": "New candy",
"category": "Confections",
"unitPrice": 8.6,
"unitsInStock": 500
}
Two built-in functions in JavaScript support conversion between JavaScript values and JSON data.
JSON.stringify()
(online ref) converts a JavaScript value into a JSON string.
let product5 = {
productName: 'New candy',
category: "Confections",
unitPrice: 8.6,
unitsInStock: 500
};
console.log(product5);
let jsonString = JSON.stringify(product5);
console.log(jsonString);
JSON.parse()
(online ref) converts a JSON string back into a JavaScript value.
// a JSON string obtained from a Web API
const jsonString = '{"id":10248,"customerId":85,"orderDate":"2012-07-04","freight":32.38,"shipCity":"Reims","lines":[{"productId":11,"unitPrice":14,"quantity":12},{"productId":42,"unitPrice":9.8,"quantity":10},{"productId":72,"unitPrice":34.8,"quantity":5}]}';
let data = JSON.parse(jsonString);
console.log(data);