This project is archived and is in readonly mode.

#4520 open
Brian Lopez

#as_json should only ever return a Hash, Array, Numeric, String, nil, true or false

Reported by Brian Lopez | May 1st, 2010 @ 07:38 PM | in 3.1

By my understanding, the #as_json method should return an object that can be nearly mapped directly to JSON (given the data types mentioned in this issue's title). This makes it so other JSON encoding libraries don't have to know or do anything special to encode the object.

If this were the expected behavior, C extension JSON libraries would be able to take advantage of the #as_json method as an optimization over calling #to_json - which may be doing it's own encoding in Ruby land.


A little backstory for the gist:
Each ActiveRecord object is having it's #to_json method called, which is falling through ActiveSupport's JSON encoder in pure ruby.
An an example in using the Mysql2 gem directly, I'm able to get pure ruby hashes and encode them in C.

The comparison isn't totally fair, since using ActiveRecord will surely be a little slower than using the db driver directly - but my hope is that you can see the benefits in returning mappable ruby types to the encoder directly.

Comments and changes to this ticket

  • Brian Lopez

    Brian Lopez May 1st, 2010 @ 07:38 PM

    • Tag set to activerecord, activesupport, json, serialization
  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:43 PM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:43 PM

    • State changed from “open” to “stale”
  • John Firebaugh

    John Firebaugh April 6th, 2011 @ 10:13 PM

    • State changed from “stale” to “open”

    I agree. It would be very useful to have the following invariant:

    ∀o, o.as_json == JSON.parse(o.to_json)

    The principal violator is ActiveModel::Serializers::JSON#as_json, which does not call #as_json on the serializable_hash. This means that the hash values are whatever types came back or were typecasted from the database (the most common non-JSON-native types being Time, Date, and DateTime). This necessitates a further workaround in Hash#encode_json which should not be necessary.

    Attaching a patch that fixes this.


  • John Firebaugh

    John Firebaugh April 7th, 2011 @ 08:44 PM

    Another issue: TrueClass, FalseClass, and NilClass return an ActiveSupport::JSON::Variable from #as_json. Instead, they should return self and override encode_json.

  • Santiago Pastorino

    Santiago Pastorino April 14th, 2011 @ 05:05 AM

    • Milestone set to 3.1
    • Assigned user set to “Santiago Pastorino”
    • Importance changed from “” to “Low”
  • rke

    rke April 25th, 2011 @ 08:54 AM

    Instead of Numeric shouldn't this be Float? does not allow Rationals or Complex numbers and although it does not impose a limit on precision and exponent, describes itself as a subset of ECMA-262 which just says:
    8.5 The Number Type
    The Number type has exactly 18437736874454810627 (that is, 264−253+3) values, representing the double- precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, ...

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>