Module: JSON

Defined in:
lib/neatjson.rb

Class Method Summary collapse

Class Method Details

.neat_generate(object, opts = {}) ⇒ String

Returns the JSON representation of the object.

Returns:

  • (String)

    the JSON representation of the object.



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
# File 'lib/neatjson.rb', line 25

def self.neat_generate(object,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
  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]}"
  colon = "#{' '*opts[:before_colon]}:#{' '*opts[:after_colon]}"

  build = ->(o,indent) do
    case o
      when String               then "#{indent}#{o.inspect}"
      when Symbol               then "#{indent}#{o.to_s.inspect}"
      when TrueClass,FalseClass then "#{indent}#{o}"
      when NilClass             then "#{indent}null"
      when Numeric
        if opts[:decimals]
          "#{indent}%.#{opts[:decimals]}f" % o
        else
          "#{indent}#{o}"
        end

      when Array
        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]
          pieces = o.map{ |v| build[ v,"#{indent} #{apad}" ] }
          pieces[0].sub! /^#{indent} #{apad}/, "#{indent}[#{apad}"
          pieces.last << apad << "]"
          pieces.join ",\n"
        else
          indent2 = "#{indent}#{opts[:indent]}"
          "#{indent}[\n#{o.map{ |x| build[ x, indent2 ] }.join ",\n"}\n#{indent}]"
        end

      when Hash
        keyvals = o.map{ |k,v| [ k.to_s.inspect, build[v,''] ] }
        keyvals = keyvals.sort_by(&:first) if opts[:sorted]
        keyvals = keyvals.map{ |a,b| [a,b].join(colon) }.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 = keyvals.sort_by(&:first) if opts[:sorted]
            keyvals[0][0].sub! "#{indent} ", "#{indent}{"
            if opts[:aligned]
              longest = keyvals.map(&:first).map(&:length).max
              keyvals.each{ |k,v| k.replace( "%-#{longest}s" % k ) }
            end
            keyvals.map! do |k,v|
              indent2 = " "*"#{k}#{colon}".length
              one_line = "#{k}#{colon}#{build[v,'']}"
              if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
                "#{k}#{colon}#{build[v,indent2].lstrip}"
              else
                one_line
              end
            end
            keyvals.last << opad << "}"
            keyvals.join ",\n"
          else
            keyvals = o.map{ |k,v| ["#{indent}#{opts[:indent]}#{k.to_s.inspect}",v] }
            keyvals = keyvals.sort_by(&:first) if opts[:sorted]
            if opts[:aligned]
              longest = keyvals.map(&:first).map(&:length).max
              keyvals.each{ |k,v| k.replace( "%-#{longest}s" % k ) }
            end
            indent2 = "#{indent}#{opts[:indent]}"
            keyvals.map! do |k,v|
              one_line = "#{k}#{colon}#{build[v,'']}"
              if opts[:wrap] && (one_line.length > opts[:wrap]) && (v.is_a?(Array) || v.is_a?(Hash))
                "#{k}#{colon}#{build[v,indent2].lstrip}"
              else
                one_line
              end
            end
            "#{indent}{\n#{keyvals.join(",\n")}\n#{indent}}"
          end
        end

      else
        "#{indent}#{o.to_json(opts)}"
    end
  end

  build[object,'']
end