aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/json/decoding.rb23
-rw-r--r--activesupport/test/json/decoding_test.rb12
3 files changed, 29 insertions, 8 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 7187d6060c..220617fefd 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -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]
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index 08446d3a83..b6370ddb0e 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -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,9 +46,13 @@ 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
end
end
end
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 01796d5e99..f0b0da32c8 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -8,8 +8,14 @@ class TestJSONDecoding < Test::Unit::TestCase
%({"returnTo":{"/categories":1}}) => {"returnTo" => {"/categories" => 1}},
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
%({"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: "'", "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,
@@ -31,4 +37,4 @@ class TestJSONDecoding < Test::Unit::TestCase
def test_failed_json_decoding
assert_raises(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) }
end
-end
+end \ No newline at end of file