The standard library's JSON gem provides two methods for encoding objects as JSON strings JSON.dump and JSON.generate.
To quote the docs, JSON.load is "is part of the implementation of the load/dump interface of Marshal and YAML.". It uses JSON.generate but calls it with a different set of options.
Analogous there is JSON.load and JSON.parse where JSON.load must not be used with untrusted user input. Typically, dump gets paired with load and generate with parse
Since we want to encode a hash as a JSON string, it makes sense to use JSON.generate rather than dump. This ensures that safe defaults will be used. The differences (default options) are as follows:
JSON.dump
JSON.generate
max_nesting
false
100
allow_nan
true
false
The max_nesting option set will ensure that no infinite loop can happen if there's circular references in the data which might be a breaking change if users are creating deeply nested JSON objects. A workaround is to not pash a hash to Faraday but instead encode it, e.g. with an increased max_nesting value, beforehand.
The allow_nan option causes JSON generation to fail if NaN, Infinity or -Infinity is encountered, e.g. JSON.generate({a: 0.0/0}) raises NaN not allowed in JSON (JSON::GeneratorError) which seems to be a sane default.
Background story how we came to notice this:
We recently ran into an odd issue with a Rails app using the Oj gem1. As of Oj version 3.11.3 there is a difference in behaviour between JSON.generate and JSON.dump. This is the output from a console in a fresh Rails app:
Because of another gem that was using Faraday Middleware internally this caused timestamps in the wrong format when generating the JSON for an external API.
The standard library's JSON gem provides two methods for encoding objects as JSON strings JSON.dump and JSON.generate.
To quote the docs, JSON.load is "is part of the implementation of the load/dump interface of Marshal and YAML.". It uses JSON.generate but calls it with a different set of options.
Analogous there is JSON.load and JSON.parse where JSON.load must not be used with untrusted user input. Typically,
dump
gets paired withload
andgenerate
withparse
Since we want to encode a hash as a JSON string, it makes sense to use JSON.generate rather than dump. This ensures that safe defaults will be used. The differences (default options) are as follows:
The max_nesting option set will ensure that no infinite loop can happen if there's circular references in the data which might be a breaking change if users are creating deeply nested JSON objects. A workaround is to not pash a hash to Faraday but instead encode it, e.g. with an increased max_nesting value, beforehand.
The allow_nan option causes JSON generation to fail if NaN, Infinity or -Infinity is encountered, e.g.
JSON.generate({a: 0.0/0})
raisesNaN not allowed in JSON (JSON::GeneratorError)
which seems to be a sane default.Background story how we came to notice this:
We recently ran into an odd issue with a Rails app using the Oj gem1. As of Oj version 3.11.3 there is a difference in behaviour between
JSON.generate
andJSON.dump
. This is the output from a console in a fresh Rails app:Because of another gem that was using Faraday Middleware internally this caused timestamps in the wrong format when generating the JSON for an external API.