Module: JSON
- Defined in:
- lib/neatjson.rb
Class Method Summary collapse
-
.neat_generate(object, opts = {}) ⇒ String
Generate the JSON string representation for an object, with a variety of formatting options.
Class Method Details
.neat_generate(object, opts = {}) ⇒ String
Generate the JSON string representation for an object, with a variety of formatting options.
The lambda for the sort
option will be passed the string name of the key, the value, and the hash for the object being sorted.
The values returned for all keys must be all comparable, or an error will occur.
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/neatjson.rb', line 35 def self.neat_generate(object,opts={}) opts ||= {} opts[:wrap] = 80 unless opts.key?(:wrap) opts[:wrap] = -1 if opts[:wrap]==true opts[:indent] ||= " " opts[:array_padding] ||= opts[:padding] || 0 opts[:object_padding] ||= opts[:padding] || 0 opts[:after_comma] ||= opts[:around_comma] || 0 opts[:before_comma] ||= opts[:around_comma] || 0 opts[:before_colon] ||= opts[:around_colon] || 0 opts[:after_colon] ||= opts[:around_colon] || 0 opts[:before_colon_1] ||= opts[:around_colon_1] || opts[:before_colon] || 0 opts[:after_colon_1] ||= opts[:around_colon_1] || opts[:after_colon] || 0 opts[:before_colon_n] ||= opts[:around_colon_n] || opts[:before_colon] || 0 opts[:after_colon_n] ||= opts[:around_colon_n] || opts[:after_colon] || 0 raise ":indent option must only be whitespace" if opts[:indent]=~/\S/ apad = " " * opts[:array_padding] opad = " " * opts[:object_padding] comma = "#{' '*opts[:before_comma]},#{' '*opts[:after_comma]}" colon1= "#{' '*opts[:before_colon_1]}:#{' '*opts[:after_colon_1]}" colonn= "#{' '*opts[:before_colon_n]}:#{' '*opts[:after_colon_n]}" memoizer = {} build = ->(o,indent) do memoizer[[o,indent]] ||= case o when String,Integer then "#{indent}#{o.inspect}" when Symbol then "#{indent}#{o.to_s.inspect}" when TrueClass,FalseClass then "#{indent}#{o}" when NilClass then "#{indent}null" when Float if o.infinite? "#{indent}#{o<0 ? "-9e9999" : "9e9999"}" elsif o.nan? "#{indent}\"NaN\"" elsif (o==o.to_i) && (o.to_s !~ /e/) build[o.to_i,indent] elsif opts[:decimals] "#{indent}%.#{opts[:decimals]}f" % o else "#{indent}#{o}" end when Array if o.empty? "#{indent}[]" else pieces = o.map{ |v| build[v,''] } one_line = "#{indent}[#{apad}#{pieces.join comma}#{apad}]" if !opts[:wrap] || (one_line.length <= opts[:wrap]) one_line elsif opts[:short] indent2 = "#{indent} #{apad}" pieces = o.map{ |v| build[ v,indent2 ] } pieces[0] = pieces[0].sub indent2, "#{indent}[#{apad}" pieces[pieces.length-1] = "#{pieces.last}#{apad}]" pieces.join ",\n" else indent2 = "#{indent}#{opts[:indent]}" "#{indent}[\n#{o.map{ |v| build[ v, indent2 ] }.join ",\n"}\n#{opts[:indent_last] ? indent2 : indent}]" end end when Hash if o.empty? "#{indent}{}" else case sort=(opts[:sorted] || opts[:sort]) when true then o = o.sort_by{|k,v| k.to_s } when Proc o = case sort.arity when 1 then o.sort_by{ |k,v| sort[k] } when 2 then o.sort_by{ |k,v| sort[k,v] } when 3 then o.sort_by{ |k,v| sort[k,v,o] } end end keyvals = o.map{ |k,v| [ k.to_s.inspect, build[v,''] ] } keyvals = keyvals.map{ |kv| kv.join(colon1) }.join(comma) one_line = "#{indent}{#{opad}#{keyvals}#{opad}}" if !opts[:wrap] || (one_line.length <= opts[:wrap]) one_line else if opts[:short] keyvals = o.map{ |k,v| ["#{indent} #{opad}#{k.to_s.inspect}",v] } keyvals[0][0] = keyvals[0][0].sub "#{indent} ", "#{indent}{" if opts[:aligned] longest = keyvals.map(&:first).map(&:length).max formatk = "%-#{longest}s" keyvals.map!{ |k,v| [ formatk % k,v] } end keyvals.map! do |k,v| indent2 = " "*"#{k}#{colonn}".length one_line = "#{k}#{colonn}#{build[v,'']}" if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash)) "#{k}#{colonn}#{build[v,indent2].lstrip}" else one_line end end "#{keyvals.join(",\n")}#{opad}}" else keyvals = o.map{ |k,v| ["#{indent}#{opts[:indent]}#{k.to_s.inspect}",v] } if opts[:aligned] longest = keyvals.map(&:first).map(&:length).max formatk = "%-#{longest}s" keyvals.map!{ |k,v| [ formatk % k,v] } end indent2 = "#{indent}#{opts[:indent]}" keyvals.map! do |k,v| one_line = "#{k}#{colonn}#{build[v,'']}" if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash)) "#{k}#{colonn}#{build[v,indent2].lstrip}" else one_line end end "#{indent}{\n#{keyvals.join(",\n")}\n#{opts[:indent_last] ? indent2 : indent}}" end end end else "#{indent}#{o.to_json(opts)}" end end build[object,''] end |