require 'rubygems' require 'blankslate' unless defined? BlankSlate require 'active_support' require 'json' module Notator #------------- class JavascriptObjectNotation < BlankSlate #------------------------------------------ def initialize( options = {} ) #------------------------------- @pretty = options[ :pretty ] || false; @context_stack = []; @context_stack.push( Hash.new ) end def hash!( key, *args, &block ) #------------------------------ method_missing( key.to_sym, *args, &block ) end alias :tag! :hash! def array!( key = nil, *args, &block ) #------------------------------------- if block.nil? raise 'Thearray! method requires an array argument.' \ unless args.first.is_a?( Array ) @context_stack.last[ key ] = args.first else array = Array.new if @context_stack.last.is_a?( Hash ) raise 'The array! method requires a key in the context of a hash.' \ if key.nil? @context_stack.last[ key ] = array else @context_stack.last.push( array ); end @context_stack.push( array ) block.call( self ) @context_stack.pop end end def value!( value = nil, &block ) #-------------------------------- raise 'The value! method can only be called in the context of ' + 'an array.' \ unless @context_stack.last.is_a?( Array ) if block.nil? @context_stack.last.push( value ) else hash = Hash.new @context_stack.last.push( hash ) @context_stack.push( hash ) block.call( self ) @context_stack.pop end end def method_missing( key, *args, &block ) #--------------------------------------- raise 'A key-value pair cannot be added in the context of an array.' \ if @context_stack.last.is_a?( Array ) if block.nil? @context_stack.last[ key ] = args.first else hash = Hash.new @context_stack.last[ key ] = hash @context_stack.push( hash ) block.call( self ) @context_stack.pop end end def <<( json ) #------------- hash = JSON[ json ] @context_stack.last.is_a?( Array ) ? @context_stack.last.push( hash ) : @context_stack.last.merge!( hash ) end def to_json #---------- @pretty ? JSON.pretty_generate( @context_stack.first ) : @context_stack.first.to_json end end end