Use JSON.generate instead of .dump in request middleware #266
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.