Meaningful heading#
Sub-Heading#
Format .json#
rails c
y my_json
Use the pretty_generate() function, built into later versions of JSON. For example:
require 'json'
my_object = { :array => [1, 2, 3, { :sample => "hash"} ], :foo => "bar" }
puts JSON.pretty_generate(my_object)
Which gets you:
{
"array": [
1,
2,
3,
{
"sample": "hash"
}
],
"foo": "bar"
}
Handy snippets re formatting json on way out#
I've put this into my ~/.irbrc:
def json_pp(json) puts JSON.pretty_generate(JSON.parse(json)) end
In the controller on action def
format.json { render :json => JSON.pretty_generate(my_json) }
More sophisticated solution#
Thanks to Rack Middleware and Rails 3 you can output pretty JSON for every request without changing any controller of your app. I have written such middleware snippet and I get nicely printed JSON in browser and curl output.
class PrettyJsonResponse
def initialize(app)
@app = app
end
def call(env)
status, headers, response = @app.call(env)
if headers["Content-Type"] =~ /^application\/json/
obj = JSON.parse(response.body)
pretty_str = JSON.pretty_unparse(obj)
response = [pretty_str]
headers["Content-Length"] = pretty_str.bytesize.to_s
end
[status, headers, response]
end
end
The above code should be placed in app/middleware/pretty_json_response.rb of your Rails project. And the final step is to register the middleware in config/environments/development.rb:
config.middleware.use PrettyJsonResponse
I don't recommend to use it in production.rb. The JSON reparsing may degrade response time and throughput of your production app. Eventually extra logic such as 'X-Pretty-Json: true' header may be introduced to trigger formatting for manual curl requests on demand.
In Rails 5 I had to change Rack::Utils.bytesize(pretty_str).to_s to pretty_str.bytesize.to_s and it works great! – panteo Jul 29 '16 at 9:28 Fantastic, thanks! I made a gem out of this: github.com/zeiv/rails_pretty_json
Using HTML code and pretty_generate is good trick:#
The
tag in HTML, used with JSON.pretty_generate, will render the JSON pretty in your view. I was so happy when my illustrious boss showed me this:<% if @data.present? %> <pre><%= JSON.pretty_generate(@data) %></pre> <% end %><% require 'json' hash = JSON[{hey: "test", num: [{one: 1, two: 2, threes: [{three: 3, tthree: 33}]}]}.to_json] %> <pre> <%= JSON.pretty_generate(hash) %> </pre>x1#
If you want to:
Prettify all outgoing JSON responses from your app automatically. Avoid polluting Object#to_json/#as_json Avoid parsing/re-rendering JSON using middleware (YUCK!) Do it the RAILS WAY! Then ... replace the ActionController::Renderer for JSON! Just add the following code to your ApplicationController:
ActionController::Renderers.add :json do |json, options| unless json.kind_of?(String) json = json.as_json(options) if json.respond_to?(:as_json) json = JSON.pretty_generate(json, options) end if options[:callback].present? self.content_type ||= Mime::JS "#{options[:callback]}(#{json})" else self.content_type ||= Mime::JSON json end endCheck out Awesome Print. Parse the JSON string into a Ruby Hash, then display it with ap like so:#
require "awesome_print" require "json" json = '{"holy": ["nested", "json"], "batman!": {"a": 1, "b": 2}}' ap(JSON.parse(json))With the above, you'll see:
{ "holy" => [ [0] "nested", [1] "json" ], "batman!" => { "a" => 1, "b" => 2 } }Dumping an ActiveRecord object to JSON (in the Rails console):#
pp User.first.as_json # => { "id" => 1, "first_name" => "Polar", "last_name" => "Bear" }to get a string from pp instead of printing to standard output, use
User.first.as_json.pretty_inspectIf you find that the pretty_generate option built into Ruby's JSON library is not "pretty" enough, I recommend my own NeatJSON gem for your formatting.#
To use it:
gem install neatjsonand then use
JSON.neat_generateinstead of
JSON.pretty_generateLike Ruby's pp it will keep objects and arrays on one line when they fit, but wrap to multiple as needed. For example:
{ "navigation.createroute.poi":[ {"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}}, {"text":"Take me to the airport","params":{"poi":"airport"}}, {"text":"Let's go to IHOP","params":{"poi":"IHOP"}}, {"text":"Show me how to get to The Med","params":{"poi":"The Med"}}, {"text":"Create a route to Arby's","params":{"poi":"Arby's"}}, { "text":"Go to the Hilton by the Airport", "params":{"poi":"Hilton","location":"Airport"} }, { "text":"Take me to the Fry's in Fresno", "params":{"poi":"Fry's","location":"Fresno"} } ], "navigation.eta":[ {"text":"When will we get there?"}, {"text":"When will I arrive?"}, {"text":"What time will I get to the destination?"}, {"text":"What time will I reach the destination?"}, {"text":"What time will it be when I arrive?"} ] }It also supports a variety of formatting options to further customize your output. For example, how many spaces before/after colons? Before/after commas? Inside the brackets of arrays and objects? Do you want to sort the keys of your object? Do you want the colons to all be lined up?
A middleware. This solution is not Rails specific--it should work with any Rack application.#
The middleware technique used here, using #each
This code goes in app/middleware/pretty_json_response.rb:
class PrettyJsonResponse def initialize(app) @app = app end def call(env) @status, @headers, @response = @app.call(env) [@status, @headers, self] end def each(&block) @response.each do |body| if @headers["Content-Type"] =~ /^application\/json/ body = pretty_print(body) end block.call(body) end end private def pretty_print(json) obj = JSON.parse(json) JSON.pretty_unparse(obj) end endTo turn it on, add this to config/environments/test.rb and config/environments/development.rb
config.middleware.use "PrettyJsonResponse"