README.md in oj-0.8.0 vs README.md in oj-0.9.0

- old
+ new

@@ -20,13 +20,13 @@ *Fast XML parser and marshaller on GitHub*: https://rubygems.org/gems/ox ## <a name="release">Release Notes</a> -### Release 0.8.0 +### Release 0.9.0 -- Auto creation of data classes when unmarshalling Objects if the Class is not defined +- Added support for circular references. ## <a name="description">Description</a> Optimized JSON (Oj), as the name implies was written to provide speed optimized JSON handling. It was designed as a faster alternative to Yajl and @@ -55,12 +55,10 @@ Oj is compatible with Ruby 1.8.7, 1.9.2, 1.9.3, JRuby, and RBX. ## <a name="plans">Planned Releases</a> -- Release 0.9: Support for circular references. - - Release 1.0: A JSON stream parser. ## <a name="compare">Comparisons</a> The following table shows the difference is speeds between several @@ -84,133 +82,153 @@ It is also worth noting that although Oj is slightly behind MessagePack for parsing, Oj serialization is much faster than MessagePack even though Oj uses human readable JSON vs the binary MessagePack format. -The results: +UOj supports circular references when in :object mode and when the :circular +flag is true. None of the other gems tested supported circular +references. They failed in the following manners when the input included +circular references. + - Yajl core dumps Ruby + + - JSON fails and raises an Exception + + - MessagePack fails and raises an Exception + +The benchmark results are: + with Object and Bignum encoding: - MessagePack failed to pack! RangeError: bignum too big to convert into `unsigned long long'. - Skipping. + > perf_strict.rb -------------------------------------------------------------------------------- Load/Parse Performance - Oj.load 100000 times in 1.384 seconds or 72230.276 load/sec. - Yajl.parse 100000 times in 2.475 seconds or 40401.331 parse/sec. - JSON::Ext.parse 100000 times in 2.562 seconds or 39037.263 parse/sec. - JSON::Pure.parse 100000 times in 20.914 seconds or 4781.518 parse/sec. - Ox.load 100000 times in 1.517 seconds or 65923.576 load/sec. + Oj:compat.load 100000 times in 1.481 seconds or 67513.146 load/sec. + Oj.load 100000 times in 1.066 seconds or 93796.400 load/sec. + JSON::Ext.parse 100000 times in 3.023 seconds or 33074.875 parse/sec. + JSON::Pure.parse 100000 times in 18.908 seconds or 5288.799 parse/sec. + Ox.load 100000 times in 1.240 seconds or 80671.900 load/sec. Summary: System time (secs) rate (ops/sec) ---------- ----------- -------------- - Oj 1.384 72230.276 - Ox 1.517 65923.576 - Yajl 2.475 40401.331 - JSON::Ext 2.562 39037.263 - JSON::Pure 20.914 4781.518 + Oj 1.066 93796.400 + Ox 1.240 80671.900 + Oj:compat 1.481 67513.146 + JSON::Ext 3.023 33074.875 + JSON::Pure 18.908 5288.799 Comparison Matrix (performance factor, 2.0 row is means twice as fast as column) - Oj Ox Yajl JSON::Ext JSON::Pure + Oj Ox Oj:compat JSON::Ext JSON::Pure ---------- ---------- ---------- ---------- ---------- ---------- - Oj 1.00 1.10 1.79 1.85 15.11 - Ox 0.91 1.00 1.63 1.69 13.79 - Yajl 0.56 0.61 1.00 1.03 8.45 - JSON::Ext 0.54 0.59 0.97 1.00 8.16 - JSON::Pure 0.07 0.07 0.12 0.12 1.00 + Oj 1.00 1.16 1.39 2.84 17.73 + Ox 0.86 1.00 1.19 2.44 15.25 + Oj:compat 0.72 0.84 1.00 2.04 12.77 + JSON::Ext 0.35 0.41 0.49 1.00 6.25 + JSON::Pure 0.06 0.07 0.08 0.16 1.00 -------------------------------------------------------------------------------- Dump/Encode/Generate Performance - Oj.dump 100000 times in 0.819 seconds or 122096.842 dump/sec. - Yajl.encode 100000 times in 2.221 seconds or 45014.913 encode/sec. - JSON::Ext.generate 100000 times in 5.082 seconds or 19678.462 generate/sec. - ***** JSON::Pure.generate failed! TypeError: wrong argument type JSON::Pure::Generator::State (expected Data) - Ox.dump 100000 times in 0.532 seconds or 188014.455 dump/sec. + Oj:compat.dump 100000 times in 0.789 seconds or 126715.249 dump/sec. + Oj.dump 100000 times in 0.457 seconds or 218798.751 dump/sec. + JSON::Ext.generate 100000 times in 4.371 seconds or 22878.630 generate/sec. + Ox.dump 100000 times in 0.501 seconds or 199425.256 dump/sec. Summary: System time (secs) rate (ops/sec) --------- ----------- -------------- - Ox 0.532 188014.455 - Oj 0.819 122096.842 - Yajl 2.221 45014.913 - JSON::Ext 5.082 19678.462 + Oj 0.457 218798.751 + Ox 0.501 199425.256 + Oj:compat 0.789 126715.249 + JSON::Ext 4.371 22878.630 Comparison Matrix (performance factor, 2.0 row is means twice as fast as column) - Ox Oj Yajl JSON::Ext + Oj Ox Oj:compat JSON::Ext --------- --------- --------- --------- --------- - Ox 1.00 1.54 4.18 9.55 - Oj 0.65 1.00 2.71 6.20 - Yajl 0.24 0.37 1.00 2.29 - JSON::Ext 0.10 0.16 0.44 1.00 + Oj 1.00 1.10 1.73 9.56 + Ox 0.91 1.00 1.57 8.72 + Oj:compat 0.58 0.64 1.00 5.54 + JSON::Ext 0.10 0.11 0.18 1.00 + + + The following packages were not included for the reason listed + ***** MessagePack: RangeError: bignum too big to convert into `unsigned long long' + ***** Yajl: RuntimeError: Yajl parse and encode did not return the same object as the original. + ***** JSON::Pure: TypeError: wrong argument type JSON::Pure::Generator::State (expected Data) -without Objects or numbers (for JSON Pure) JSON: +without Objects or numbers (for JSON Pure, Yajl, and Messagepack) JSON: -------------------------------------------------------------------------------- Load/Parse Performance - Oj.load 100000 times in 0.737 seconds or 135683.185 load/sec. - Yajl.parse 100000 times in 1.352 seconds or 73978.778 parse/sec. - JSON::Ext.parse 100000 times in 1.433 seconds or 69780.554 parse/sec. - JSON::Pure.parse 100000 times in 12.974 seconds or 7707.624 parse/sec. - Ox.load 100000 times in 0.904 seconds or 110596.591 load/sec. - MessagePack.unpack 100000 times in 0.644 seconds or 155281.191 unpack/sec. + Oj:compat.load 100000 times in 0.806 seconds or 124051.164 load/sec. + Oj.load 100000 times in 0.810 seconds or 123384.587 load/sec. + Yajl.parse 100000 times in 1.441 seconds or 69385.996 parse/sec. + JSON::Ext.parse 100000 times in 1.567 seconds or 63797.848 parse/sec. + JSON::Pure.parse 100000 times in 13.500 seconds or 7407.247 parse/sec. + Ox.load 100000 times in 0.954 seconds or 104836.748 load/sec. + MessagePack.unpack 100000 times in 0.651 seconds or 153707.817 unpack/sec. Summary: System time (secs) rate (ops/sec) ----------- ----------- -------------- - MessagePack 0.644 155281.191 - Oj 0.737 135683.185 - Ox 0.904 110596.591 - Yajl 1.352 73978.778 - JSON::Ext 1.433 69780.554 - JSON::Pure 12.974 7707.624 + MessagePack 0.651 153707.817 + Oj:compat 0.806 124051.164 + Oj 0.810 123384.587 + Ox 0.954 104836.748 + Yajl 1.441 69385.996 + JSON::Ext 1.567 63797.848 + JSON::Pure 13.500 7407.247 Comparison Matrix (performance factor, 2.0 row is means twice as fast as column) - MessagePack Oj Ox Yajl JSON::Ext JSON::Pure - ----------- ----------- ----------- ----------- ----------- ----------- ----------- - MessagePack 1.00 1.14 1.40 2.10 2.23 20.15 - Oj 0.87 1.00 1.23 1.83 1.94 17.60 - Ox 0.71 0.82 1.00 1.49 1.58 14.35 - Yajl 0.48 0.55 0.67 1.00 1.06 9.60 - JSON::Ext 0.45 0.51 0.63 0.94 1.00 9.05 - JSON::Pure 0.05 0.06 0.07 0.10 0.11 1.00 + MessagePack Oj:compat Oj Ox Yajl JSON::Ext JSON::Pure + ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- + MessagePack 1.00 1.24 1.25 1.47 2.22 2.41 20.75 + Oj:compat 0.81 1.00 1.01 1.18 1.79 1.94 16.75 + Oj 0.80 0.99 1.00 1.18 1.78 1.93 16.66 + Ox 0.68 0.85 0.85 1.00 1.51 1.64 14.15 + Yajl 0.45 0.56 0.56 0.66 1.00 1.09 9.37 + JSON::Ext 0.42 0.51 0.52 0.61 0.92 1.00 8.61 + JSON::Pure 0.05 0.06 0.06 0.07 0.11 0.12 1.00 -------------------------------------------------------------------------------- Dump/Encode/Generate Performance - Oj.dump 100000 times in 0.161 seconds or 620058.906 dump/sec. - Yajl.encode 100000 times in 0.765 seconds or 130637.498 encode/sec. - JSON::Ext.generate 100000 times in 3.306 seconds or 30250.212 generate/sec. - JSON::Pure.generate 100000 times in 7.067 seconds or 14150.026 generate/sec. - Ox.dump 100000 times in 0.178 seconds or 561312.123 dump/sec. - MessagePack.pack 100000 times in 0.306 seconds or 326301.535 pack/sec. + Oj:compat.dump 100000 times in 0.173 seconds or 578526.262 dump/sec. + Oj.dump 100000 times in 0.179 seconds or 558362.880 dump/sec. + Yajl.encode 100000 times in 0.776 seconds or 128794.279 encode/sec. + JSON::Ext.generate 100000 times in 3.511 seconds or 28483.812 generate/sec. + JSON::Pure.generate 100000 times in 7.389 seconds or 13533.717 generate/sec. + Ox.dump 100000 times in 0.196 seconds or 510589.629 dump/sec. + MessagePack.pack 100000 times in 0.317 seconds or 315307.220 pack/sec. Summary: System time (secs) rate (ops/sec) ----------- ----------- -------------- - Oj 0.161 620058.906 - Ox 0.178 561312.123 - MessagePack 0.306 326301.535 - Yajl 0.765 130637.498 - JSON::Ext 3.306 30250.212 - JSON::Pure 7.067 14150.026 + Oj:compat 0.173 578526.262 + Oj 0.179 558362.880 + Ox 0.196 510589.629 + MessagePack 0.317 315307.220 + Yajl 0.776 128794.279 + JSON::Ext 3.511 28483.812 + JSON::Pure 7.389 13533.717 Comparison Matrix (performance factor, 2.0 row is means twice as fast as column) - Oj Ox MessagePack Yajl JSON::Ext JSON::Pure - ----------- ----------- ----------- ----------- ----------- ----------- ----------- - Oj 1.00 1.10 1.90 4.75 20.50 43.82 - Ox 0.91 1.00 1.72 4.30 18.56 39.67 - MessagePack 0.53 0.58 1.00 2.50 10.79 23.06 - Yajl 0.21 0.23 0.40 1.00 4.32 9.23 - JSON::Ext 0.05 0.05 0.09 0.23 1.00 2.14 - JSON::Pure 0.02 0.03 0.04 0.11 0.47 1.00 + Oj:compat Oj Ox MessagePack Yajl JSON::Ext JSON::Pure + ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- + Oj:compat 1.00 1.04 1.13 1.83 4.49 20.31 42.75 + Oj 0.97 1.00 1.09 1.77 4.34 19.60 41.26 + Ox 0.88 0.91 1.00 1.62 3.96 17.93 37.73 + MessagePack 0.55 0.56 0.62 1.00 2.45 11.07 23.30 + Yajl 0.22 0.23 0.25 0.41 1.00 4.52 9.52 + JSON::Ext 0.05 0.05 0.06 0.09 0.22 1.00 2.10 + JSON::Pure 0.02 0.02 0.03 0.04 0.11 0.48 1.00 - ### Simple JSON Writing and Parsing: require 'oj' h = { 'one' => 1, 'array' => [ true, false ] } @@ -236,42 +254,83 @@ formating follows the following rules. 1. JSON native types, true, false, nil, String, Hash, Array, and Number are encoded normally. -2. If a Hash uses Symbols as keys those keys appear as Strings with a leading -':' character. +2. A Symbol is encoded as a JSON string with a preceeding `:` character. -3. The '^' character denotes a special key value when in a JSON Object sequence. +3. The `^` character denotes a special key value when in a JSON Object sequence. -4. If a String begins with a ':' character such as ':abc' it is encoded as {"^s":":abc"}. +4. A Ruby String that starts with `:` or the sequence `^i` or `^r` are encoded by +excaping the first character so that it appears as `\u005e` or `\u003a` instead of +`:` or `^`. -5. If a Symbol begins with a ':' character such as :":abc" is is encoded as {"^m":":abc"}. +5. A `"^c"` JSON Object key indicates the value should be converted to a Ruby +class. The sequence `{"^c":"Oj::Bag"}` is read as the Oj::Bag class. -6. A "^c" JSON Object key indicates the value should be converted to a Ruby -class. The sequence {"^c":"Oj::Bag"} is read as the Oj::Bag class. +6. A `"^t"` JSON Object key indicates the value should be converted to a Ruby +Time. The sequence `{"^t":1325775487.000000}` is read as Jan 5, 2012 at 23:58:07. -7. A "^t" JSON Object key indicates the value should be converted to a Ruby -Time. The sequence {"^t":1325775487.000000} is read as Jan 5, 2012 at -23:58:07. - -8. A "^o" JSON Object key indicates the value should be converted to a Ruby -Object. The first entry in the JSON Object must be a class with the "^o" +87. A `"^o"` JSON Object key indicates the value should be converted to a Ruby +Object. The first entry in the JSON Object must be a class with the `"^o"` key. After that each entry is treated as a variable of the Object where the -key is the variable name without the preceeding '@'. An example is -{"^o":"Oj::Bag","x":58,"y":"marbles"}. +key is the variable name without the preceeding `@`. An example is +`{"^o":"Oj::Bag","x":58,"y":"marbles"}`. -9. When encoding an Object, if the variable name does not begin with an '@' -character then the name preceeded by a '~' character. This occurs in the -Exception class. An example is {"^o":"StandardError","~mesg":"A -Message","~bt":[".\/tests.rb:345:in `test_exception'"]} +8. A `"^u"` JSON Object key indicates the value should be converted to a Ruby +Struct. The first entry in the JSON Object must be a class with the `"^u"` +key. After that each entry is is given a numeric position in the struct and +that is used as the key in the JSON Object. An example is `{"^u":["Range",1,7,false]}`. +9. When encoding an Object, if the variable name does not begin with an `@` +character then the name preceeded by a `~` character. This occurs in the +Exception class. An example is `{"^o":"StandardError","~mesg":"A Message","~bt":[".\/tests.rb:345:in `test_exception'"]}`. + 10. If a Hash entry has a key that is not a String or Symbol then the entry is -encoded with a key of the form "^#n" where n is a hex number. The value that +encoded with a key of the form `"^#n"` where n is a hex number. The value that is an Array where the first element is the key in the Hash and the second is -the value. An example is {"^#3":[2,5]}. +the value. An example is `{"^#3":[2,5]}`. -11. A "^i" JSON entry in either an Object or Array is the ID of the Ruby +11. A `"^i"` JSON entry in either an Object or Array is the ID of the Ruby Object being encoded. It is used when the :circular flag is set. It can appear -in either a JSON Object or in a JSON Array. If alone it represented a link to -the original Hash or JSON. If an added attribute it is the ID of the original -Object or Array. Examples are TBD. +in either a JSON Object or in a JSON Array. In an Object the `"^i"` key has a +corresponding reference Fixnum. In an array the sequence will include an +embedded reference number. An example is +`{"^o":"Oj::Bag","^i":1,"x":["^i2",true],"me":"^r1"}`. + +12. A `"^r"` JSON entry in an Object is a references to a Object or Array that +already appears in the JSON String. It must match up with a previous `"^i"` +ID. An example is `{"^o":"Oj::Bag","^i":1,"x":3,"me":"^r1"}`. + +13. If an Array element is a String and starts with `"^i"` then the first +character, the `^` is encoded as a hex character sequence. An example is +`["\u005ei37",3]`. + +### License: + + Copyright (c) 2012, Peter Ohler + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of Peter Ohler nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.