INDENT_SIZE = 2 def pretty_jsonify(struct, indent=0) case struct when Array "[\n" + indent_str("", indent+INDENT_SIZE) + struct.map { |value| pretty_jsonify(value, indent+INDENT_SIZE) }.join(",\n#{indent_str('', indent+INDENT_SIZE)}") + "\n" + indent_str("]", indent) when Hash "{\n" + indent_str("", indent+INDENT_SIZE) + struct.map { |key, value| pretty_jsonify(key, indent+INDENT_SIZE) + ": " + pretty_jsonify(value, indent+INDENT_SIZE) }.join(",\n#{indent_str('', indent+INDENT_SIZE)}") + "\n" + indent_str("}", indent) when nil "null" when Numeric "#{struct}" when TrueClass "true" when FalseClass "false" else "\"#{struct}\"" end end def indent_str(str, indent) " "*indent + str end cases = [ { i: 'foo', o: '"foo"' }, { i: 1, o: '1' }, { i: 1.5, o: '1.5' }, { i: true, o: 'true' }, { i: nil, o: 'null' }, { i: { foo: 'bar', baz: 'buzz' }, o: %Q#{\n "foo": "bar",\n "baz": "buzz"\n}# }, { i: ['a', 'b', 'c'], o: %Q#[\n "a",\n "b",\n "c"\n]# }, { i: { foo: 'bar', baz: { fizz: 'buzz', waz: 1 }, wiz: [ 2, { fuzz: true }, nil, [ 'a', 'b' ] ] }, o: %Q{{\n "foo": "bar",\n "baz": {\n "fizz": "buzz",\n "waz": 1\n },\n "wiz": [\n 2,\n {\n "fuzz": true\n },\n null,\n [\n "a",\n "b"\n ]\n ]\n}} } ] cases.each_with_index { |c, idx| if pretty_jsonify(c[:i]) == c[:o] puts "Test case #{idx} PASSED:\n#{c[:o]}" else puts "Test case #{idx} FAILED:\n#{pretty_jsonify(c[:i])}\nvs\n#{c[:o]}" end }