require 'sinatra/base'
module Sinatra
# = Sinatra::JSON
#
# Sinatra::JSON adds a helper method, called +json+, for (obviously)
# json generation.
#
# == Usage
#
# === Classic Application
#
# In a classic application simply require the helper, and start using it:
#
# require "sinatra"
# require "sinatra/json"
#
# # define a route that uses the helper
# get '/' do
# json :foo => 'bar'
# end
#
# # The rest of your classic application code goes here...
#
# === Modular Application
#
# In a modular application you need to require the helper, and then tell the
# application you will use it:
#
# require "sinatra/base"
# require "sinatra/json"
#
# class MyApp < Sinatra::Base
# helpers Sinatra::JSON
#
# # define a route that uses the helper
# get '/' do
# json :foo => 'bar'
# end
#
# # The rest of your modular application code goes here...
# end
#
# === Encoders
#
# By default it will try to call +to_json+ on the object, but if it doesn't
# respond to that message, it will use its own rather simple encoder. You can
# easily change that anyways. To use +JSON+, simply require it:
#
# require 'json'
#
# The same goes for Yajl::Encoder:
#
# require 'yajl'
#
# For other encoders, besides requiring them, you need to define the
# :json_encoder setting. For instance, for the +Whatever+ encoder:
#
# require 'whatever'
# set :json_encoder, Whatever
#
# To force +json+ to simply call +to_json+ on the object:
#
# set :json_encoder, :to_json
#
# Actually, it can call any method:
#
# set :json_encoder, :my_fancy_json_method
#
# === Content-Type
#
# It will automatically set the content type to "application/json". As
# usual, you can easily change that, with the :json_content_type
# setting:
#
# set :json_content_type, :js
#
# === Overriding the Encoder and the Content-Type
#
# The +json+ helper will also take two options :encoder and
# :content_type. The values of this options are the same as the
# :json_encoder and :json_content_type settings,
# respectively. You can also pass those to the json method:
#
# get '/' do
# json({:foo => 'bar'}, :encoder => :to_json, :content_type => :js)
# end
#
module JSON
class << self
def encode(object)
::MultiJson.dump(object)
end
end
def json(object, options = {})
content_type resolve_content_type(options)
resolve_encoder_action object, resolve_encoder(options)
end
private
def resolve_content_type(options = {})
options[:content_type] || settings.json_content_type
end
def resolve_encoder(options = {})
options[:json_encoder] || settings.json_encoder
end
def resolve_encoder_action(object, encoder)
[:encode, :generate].each do |method|
return encoder.send(method, object) if encoder.respond_to? method
end
if encoder.is_a? Symbol
object.__send__(encoder)
else
fail "#{encoder} does not respond to #generate nor #encode"
end #if
end #resolve_encoder_action
end #JSON
Base.set :json_encoder do
::MultiJson
end
Base.set :json_content_type, :json
helpers JSON
end