diff options
author | Godfrey Chan <godfreykfc@gmail.com> | 2013-11-05 21:01:38 -0800 |
---|---|---|
committer | Godfrey Chan <godfreykfc@gmail.com> | 2013-11-06 17:16:11 -0800 |
commit | 798881ecd4510b9e1e5e10529fc2d81b9deb961e (patch) | |
tree | 5518edc1602caa1f36985f9ea8f9a725fa99fed2 /activesupport/lib/active_support/core_ext/object/json.rb | |
parent | 6da5ff45c6d69912fb96870f31aaf0c0590fa212 (diff) | |
download | rails-798881ecd4510b9e1e5e10529fc2d81b9deb961e.tar.gz rails-798881ecd4510b9e1e5e10529fc2d81b9deb961e.tar.bz2 rails-798881ecd4510b9e1e5e10529fc2d81b9deb961e.zip |
Do not expose internal state in the public encoder API (i.e. as_json)
See [1] for why this is not a good idea.
As part of this refactor, circular reference protection in as_json has
been removed and the corresponding error class has been deprecated.
As discussed with @jeremy, circular reference error is considered
programmer errors and protecting against it is out of scope for
the encoder.
This is again based on the excellent work by @sergiocampama in #11728.
[1]: https://github.com/intridea/multi_json/pull/138#issuecomment-24468223
Diffstat (limited to 'activesupport/lib/active_support/core_ext/object/json.rb')
-rw-r--r-- | activesupport/lib/active_support/core_ext/object/json.rb | 19 |
1 files changed, 4 insertions, 15 deletions
diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb index e2a89f5760..34b76e228a 100644 --- a/activesupport/lib/active_support/core_ext/object/json.rb +++ b/activesupport/lib/active_support/core_ext/object/json.rb @@ -139,14 +139,11 @@ end class Array def as_json(options = nil) #:nodoc: - # use encoder as a proxy to call as_json on all elements, to protect from circular references - encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options) - map { |v| encoder.as_json(v, options) } + map { |v| v.as_json(options && options.dup) } end def encode_json(encoder) #:nodoc: - # we assume here that the encoder has already run as_json on self and the elements, so we run encode_json directly - "[#{map { |v| v.encode_json(encoder) } * ','}]" + "[#{map { |v| v.as_json.encode_json(encoder) } * ','}]" end end @@ -165,19 +162,11 @@ class Hash self end - # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references - encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options) - Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }] + Hash[subset.map { |k, v| [k.to_s, v.as_json(options && options.dup)] }] end def encode_json(encoder) #:nodoc: - # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be - # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields); - - # on the other hand, we need to run as_json on the elements, because the model representation may contain fields - # like Time/Date in their original (not jsonified) form, etc. - - "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}" + "{#{map { |k,v| "#{k.as_json.encode_json(encoder)}:#{v.as_json.encode_json(encoder)}" } * ','}}" end end |