Decode json strings as Dates/Times if they're using a YAML-compatible format. Closes #9614 [Rick]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7613 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
911ea2f26f
commit
2a60093fa3
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Decode json strings as Dates/Times if they're using a YAML-compatible format. Closes #9614 [Rick]
|
||||
|
||||
* Fixed cache_page to use the request url instead of the routing options when picking a save path #8614 [josh]
|
||||
|
||||
* Object.subclasses_of includes anonymous subclasses. [Jeremy Kemper]
|
||||
|
|
|
@ -15,17 +15,26 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
protected
|
||||
# matches YAML-formatted dates
|
||||
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})?)?$/
|
||||
|
||||
# Ensure that ":" and "," are always followed by a space
|
||||
def convert_json_to_yaml(json) #:nodoc:
|
||||
scanner, quoting, marks = StringScanner.new(json), false, []
|
||||
|
||||
scanner, quoting, marks, pos, times = StringScanner.new(json), false, [], nil, []
|
||||
while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
|
||||
case char = scanner[1]
|
||||
when '"', "'"
|
||||
if !quoting
|
||||
quoting = char
|
||||
pos = scanner.pos
|
||||
elsif quoting == char
|
||||
if json[pos..scanner.pos-2] =~ DATE_REGEX
|
||||
# found a date, track the exact positions of the quotes so we can remove them later.
|
||||
# oh, and increment them for each current mark, each one is an extra padded space that bumps
|
||||
# the position in the final yaml output
|
||||
total_marks = marks.size
|
||||
times << pos+total_marks << scanner.pos+total_marks
|
||||
end
|
||||
quoting = false
|
||||
end
|
||||
when ":",","
|
||||
|
@ -37,7 +46,11 @@ module ActiveSupport
|
|||
json
|
||||
else
|
||||
ranges = ([0] + marks.map(&:succ)).zip(marks + [json.length])
|
||||
ranges.map { |(left, right)| json[left..right] }.join(" ")
|
||||
output = ranges.collect! { |(left, right)| json[left..right] }.join(" ")
|
||||
times.each do |pos|
|
||||
output[pos-1] = ' '
|
||||
end
|
||||
output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,12 @@ class TestJSONDecoding < Test::Unit::TestCase
|
|||
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
|
||||
%({a: "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
|
||||
%({a: "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
|
||||
%({a: "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
|
||||
%({a: "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
|
||||
# no time zone
|
||||
%({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
|
||||
# needs to be *exact*
|
||||
%({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "},
|
||||
%([]) => [],
|
||||
%({}) => {},
|
||||
%(1) => 1,
|
||||
|
|
Loading…
Reference in New Issue