A wrapper around Fetch just for JSON
Why would you fetch anything but json? ;)
In a web page:
<script src=fetch-json.min.js></script>
or from the jsdelivr.com CDN:
<script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/fetch-json.min.js></script>
Install package:
$ npm install node-fetch fetch-json
and then import:
const fetchJson = require('fetch-json');
Fetch the NASA Astronomy Picture of the Day:
// NASA APoD
const url = 'https://api.nasa.gov/planetary/apod';
const params = { api_key: 'DEMO_KEY' };
const handleData = (data) =>
console.log('The NASA APoD for today is at: ' + data.url);
fetchJson.get(url, params).then(handleData);
Create a resource for the planet Jupiter:
// Create Jupiter
const resource = { name: 'Jupiter', position: 5 };
const handleData = (data) =>
console.log('Planet:', data); //http response body as an object literal
fetchJson.post('https://httpbin.org/post', resource)
.then(handleData)
.catch(console.error);
For more examples, see the Mocha specification cases:
spec-node.js (Mocha output on Travis CI)
fetch-json calls the native Fetch API if in a web browser and calls node-fetch if running on node.
For comparison, the above POST example to create a planet would be done calling the Fetch API directly with the code:
// Create Jupiter (with Fetch API instead of fetch-json)
const resource = { name: 'Jupiter', position: 5 };
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(resource)
};
const handleData = (data) =>
console.log(data); //http response body as an object literal
fetch('https://httpbin.org/post', options)
.then(response => response.json())
.then(handleData)
.catch(console.error);
The examples for fetch-json and the Fetch API each produce the same output.
fetch-json makes REST easy — it automatically:
- Serializes the body payload with
JSON.stringify()
- Adds the
application/json
HTTP header to set the data type - Appends the GET
params
object items to the URL - Runs
.json()
on the response - Sets
credentials
to'same-origin'
(support user sessions in Grails, Rails, PHP, Flask, etc.) - Converts text responses into JSON (convenient for HTTP errors)
The format for using fetch-json is:
fetchJson.get(url, params, options).then(callback);
fetchJson.post(url, resource, options).then(callback);
fetchJson.put(url, resource, options).then(callback);
fetchJson.patch(url, resource, options).then(callback);
fetchJson.delete(url, resource, options).then(callback);
Notes:
- Only the
url
parameter is required. The other parameters are optional. - The
params
object forfetchJson.get()
is converted into a query string and appended to theurl
. - The
resource
object is turned into the body of the HTTP request. - The
options
parameter is passed through to the Fetch API (see theinit
documentation on MDN).
If you need to programmatically set the method, use the format:
fetchJson.request(method, url, data, options).then(callback);
Where method
is 'GET'
, 'POST'
, 'PUT'
, 'PATCH'
, or 'DELETE'
, and data
represents
either params
or resource
.
Enable basic logging to the console with:
fetchJson.enableLogger();
To use a custom logger, pass in a function that accepts 9 parameters to log.
To disable logging, pass in false
.
To get an array containing the names of the parameters:
fetchJson.getLogHeaders();
The default console output looks like:
2018-09-12T07:20:12.372Z – "request" - "GET" – "api.nasa.gov" – "https://api.nasa.gov/planetary/apod"
2018-09-12T07:20:13.009Z – "response" - "GET" – "api.nasa.gov" – "https://api.nasa.gov/planetary/apod" - true - 200 - "OK" - "application/json"
The HTTP response body is considered to be JSON if the Content-Type
is "application/json"
or
"text/javascript"
. If the HTTP response body is not JSON, an object containing the body as a
string in the bodyText
field is created and passed on through the promise.
In addition to the bodyText
field, the object will have the fields: ok
, status
, statusText
,
and contentType
.
For example, an HTTP response for an error status of 500 would be converted to an object similar to:
{
ok: false,
status: 500,
statusText: 'INTERNAL SERVER ERROR',
contentType: 'text/html; charset=utf-8',
bodyText: '<!doctype html><html><body>Server Error</body></html>'
}
With fetch-json, you know the response body will always be passed back to you as a simple object literal.
To support really old browsers, include polyfills for Promise and Fetch API:
<script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/polyfill.min.js></script>
<script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/fetch.umd.min.js></script>
Note:
JSDOM does not include fetch
, so you need to add a polyfill (see usage of whatwg-fetch
in
spec-jsdom.js and
gulpfile.js.
Feel free to submit an issue.
"Stop trying to make fetch happen without #fetchJson!"