1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
require 'sinatra/base'
require 'multi_json'
module Sinatra
# = Sinatra::JSON
#
# <tt>Sinatra::JSON</tt> 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
#
# # 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 <tt>Yajl::Encoder</tt>:
#
# require 'yajl'
#
# For other encoders, besides requiring them, you need to define the
# <tt>:json_encoder</tt> 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 <tt>:json_content_type</tt>
# setting:
#
# set :json_content_type, :js
#
# === Overriding the Encoder and the Content-Type
#
# The +json+ helper will also take two options <tt>:encoder</tt> and
# <tt>:content_type</tt>. The values of this options are the same as the
# <tt>:json_encoder</tt> and <tt>:json_content_type</tt> 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
# Load the JSON helpers in modular style automatically
Base.helpers JSON
end
|