Skip to content

Commit

Permalink
Pulling multi_json directly into the library.
Browse files Browse the repository at this point in the history
  • Loading branch information
hoxworth committed Feb 14, 2012
1 parent f218458 commit 2ff9296
Show file tree
Hide file tree
Showing 13 changed files with 839 additions and 5 deletions.
20 changes: 20 additions & 0 deletions LICENSE-multi_json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright (c) 2010 Michael Bleigh, Josh Kalderimis, Erik Michaels-Ober, and Intridea, Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
File renamed without changes.
3 changes: 1 addition & 2 deletions json-schema.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ spec = Gem::Specification.new do |s|
s.files = Dir[ "lib/**/*", "resources/*.json" ]
s.require_path = "lib"
s.test_files = Dir[ "test/**/test*", "test/{data,schemas}/*.json" ]
s.extra_rdoc_files = ["README.textile"]
s.add_dependency 'multi_json', '~> 1.0.4'
s.extra_rdoc_files = ["README.textile","LICENSE.md","LICENSE-multi_json.md"]
end
22 changes: 20 additions & 2 deletions lib/json-schema.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
require 'multi_json'
require 'rubygems'

def load_gem gemname
if begin
Gem::Specification::find_by_name(gemname)
rescue Gem::LoadError
false
rescue
Gem.available?(gemname)
end
require gemname
end
end

load_gem('yajl')
load_gem('json')

require File.join(File.dirname(__FILE__),"json-schema/lib/multi_json/multi_json.rb")

# Force MultiJson to load an engine before we define the JSON constant here; otherwise,
# it looks for things that are under the JSON namespace that aren't there (since we have defined it here)
MultiJson.engine
Expand All @@ -10,4 +28,4 @@
require 'validator'
Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/*.rb")].each {|file| require file }
Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].each {|file| require file }
require 'uri/file'
require 'uri/file'
85 changes: 85 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module MultiJson
class DecodeError < StandardError
attr_reader :data
def initialize(message, backtrace, data)
super(message)
self.set_backtrace(backtrace)
@data = data
end
end

module_function

@engine = nil

# Get the current engine class.
def engine
return @engine if @engine
self.engine = self.default_engine
@engine
end

REQUIREMENT_MAP = [
["yajl", :yajl],
["json", :json_gem],
["json/pure", :json_pure]
]

DEFAULT_ENGINE_WARNING = 'Warning: multi_json is using default ok_json engine. Suggested action: require and load an appropriate JSON library.'

# The default engine based on what you currently
# have loaded and installed. First checks to see
# if any engines are already loaded, then checks
# to see which are installed if none are loaded.
def default_engine
return :yajl if defined?(::Yajl)
return :json_gem if defined?(::JSON)

REQUIREMENT_MAP.each do |(library, engine)|
begin
require library
return engine
rescue LoadError
next
end
end

Kernel.warn DEFAULT_ENGINE_WARNING
:ok_json
end

# Set the JSON parser utilizing a symbol, string, or class.
# Supported by default are:
#
# * <tt>:json_gem</tt>
# * <tt>:json_pure</tt>
# * <tt>:ok_json</tt>
# * <tt>:yajl</tt>
def engine=(new_engine)
case new_engine
when String, Symbol
require File.join(File.dirname(__FILE__),"multi_json/engines/#{new_engine}")
@engine = MultiJson::Engines.const_get("#{new_engine.to_s.split('_').map{|s| s.capitalize}.join('')}")
when Class
@engine = new_engine
else
raise "Did not recognize your engine specification. Please specify either a symbol or a class."
end
end

# Decode a JSON string into Ruby.
#
# <b>Options</b>
#
# <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
def decode(string, options = {})
engine.decode(string, options)
rescue engine::ParseError => exception
raise DecodeError.new(exception.message, exception.backtrace, string)
end

# Encodes a Ruby object as JSON.
def encode(object, options = {})
engine.encode(object, options)
end
end
27 changes: 27 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json/engines/json_common.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module MultiJson
module Engines
module JsonCommon

def decode(string, options = {})
opts = {}
opts[:symbolize_names] = options[:symbolize_keys]
string = string.read if string.respond_to?(:read)
::JSON.parse(string, opts)
end

def encode(object, options = {})
object.to_json(process_options(options))
end

protected

def process_options(options={})
return options if options.empty?
opts = {}
opts.merge!(JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty)
opts.merge! options
end

end
end
end
12 changes: 12 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json/engines/json_gem.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'json' unless defined?(::JSON)
require File.join(File.dirname(__FILE__),'../engines/json_common')

module MultiJson
module Engines
# Use the JSON gem to encode/decode.
class JsonGem
ParseError = ::JSON::ParserError
extend JsonCommon
end
end
end
12 changes: 12 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json/engines/json_pure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'json/pure' unless defined?(::JSON)
require File.join(File.dirname(__FILE__),'../engines/json_common')

module MultiJson
module Engines
# Use JSON pure to encode/decode.
class JsonPure
ParseError = ::JSON::ParserError
extend JsonCommon
end
end
end
48 changes: 48 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json/engines/ok_json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require File.join(File.dirname(__FILE__), "../vendor/ok_json")

module MultiJson
module Engines
class OkJson
ParseError = ::MultiJson::OkJson::Error

def self.decode(string, options = {}) #:nodoc:
string = string.read if string.respond_to?(:read)
result = ::MultiJson::OkJson.decode(string)
options[:symbolize_keys] ? symbolize_keys(result) : result
end

def self.encode(object, options = {}) #:nodoc:
::MultiJson::OkJson.valenc(stringify_keys(object))
end

def self.symbolize_keys(object) #:nodoc:
modify_keys(object) do |key|
key.is_a?(String) ? key.to_sym : key
end
end

def self.stringify_keys(object) #:nodoc:
modify_keys(object) do |key|
key.is_a?(Symbol) ? key.to_s : key
end
end

def self.modify_keys(object, &modifier) #:nodoc:
case object
when Array
object.map do |value|
modify_keys(value, &modifier)
end
when Hash
object.inject({}) do |result, (key, value)|
new_key = modifier.call(key)
new_value = modify_keys(value, &modifier)
result.merge! new_key => new_value
end
else
object
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/json-schema/lib/multi_json/multi_json/engines/yajl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'yajl' unless defined?(Yajl)

module MultiJson
module Engines
# Use the Yajl-Ruby library to encode/decode.
class Yajl
ParseError = ::Yajl::ParseError

def self.decode(string, options = {}) #:nodoc:
::Yajl::Parser.new(:symbolize_keys => options[:symbolize_keys]).parse(string)
end

def self.encode(object, options = {}) #:nodoc:
::Yajl::Encoder.encode(object, options)
end
end
end
end
Loading

0 comments on commit 2ff9296

Please sign in to comment.