提交 2a60093f 编写于 作者: R Rick Olson

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
上级 911ea2f2
*SVN* *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] * 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] * Object.subclasses_of includes anonymous subclasses. [Jeremy Kemper]
......
...@@ -15,17 +15,26 @@ def decode(json) ...@@ -15,17 +15,26 @@ def decode(json)
end end
protected 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 # Ensure that ":" and "," are always followed by a space
def convert_json_to_yaml(json) #:nodoc: 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(/(\\['"]|['":,\\]|\\.)/) while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
case char = scanner[1] case char = scanner[1]
when '"', "'" when '"', "'"
if !quoting if !quoting
quoting = char quoting = char
pos = scanner.pos
elsif quoting == char 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 quoting = false
end end
when ":","," when ":",","
...@@ -37,7 +46,11 @@ def convert_json_to_yaml(json) #:nodoc: ...@@ -37,7 +46,11 @@ def convert_json_to_yaml(json) #:nodoc:
json json
else else
ranges = ([0] + marks.map(&:succ)).zip(marks + [json.length]) 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
......
...@@ -10,6 +10,12 @@ class TestJSONDecoding < Test::Unit::TestCase ...@@ -10,6 +10,12 @@ class TestJSONDecoding < Test::Unit::TestCase
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]}, %({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
%({a: "'", "b": "5,000"}) => {"a" => "'", "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: "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, %(1) => 1,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册