6 class ParseError
< StandardError
10 # Converts a JSON string into a Ruby object.
12 YAML
.load(convert_json_to_yaml(json
))
13 rescue ArgumentError
=> e
14 raise ParseError
, "Invalid JSON string"
18 # matches YAML-formatted dates
19 DATE_REGEX
= /^\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?$/
21 # Ensure that ":" and "," are always followed by a space
22 def convert_json_to_yaml(json
) #:nodoc:
23 scanner
, quoting
, marks
, pos
, times
= StringScanner
.new(json
), false, [], nil, []
24 while scanner
.scan_until(/(\\['"]|['":,\\]|\\.)/)
25 case char
= scanner
[1]
31 if json
[pos
..scanner
.pos-2
] =~ DATE_REGEX
32 # found a date, track the exact positions of the quotes so we can remove them later.
33 # oh, and increment them for each current mark, each one is an extra padded space that bumps
34 # the position in the final YAML output
35 total_marks
= marks
.size
36 times
<< pos
+total_marks
<< scanner
.pos
+total_marks
41 marks
<< scanner
.pos
- 1 unless quoting
46 json
.gsub(/\\\//, '/')
48 left_pos = [-1].push(*marks)
49 right_pos = marks << json.length
51 left_pos.each_with_index do |left, i|
52 output << json[left.succ..right_pos[i]]
56 times.each { |i| output[i-1] = ' ' }
57 output.gsub!(/\\\//, '/')