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*
|
*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 @@ module ActiveSupport
|
||||||
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,9 +46,13 @@ module ActiveSupport
|
||||||
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,14 @@ class TestJSONDecoding < Test::Unit::TestCase
|
||||||
%({"returnTo":{"/categories":1}}) => {"returnTo" => {"/categories" => 1}},
|
%({"returnTo":{"/categories":1}}) => {"returnTo" => {"/categories" => 1}},
|
||||||
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
||||||
%({"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,
|
||||||
|
@ -31,4 +37,4 @@ class TestJSONDecoding < Test::Unit::TestCase
|
||||||
def test_failed_json_decoding
|
def test_failed_json_decoding
|
||||||
assert_raises(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) }
|
assert_raises(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) }
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue