Oj Object Encoding Format

peter@ohler.com

Author: Peter Ohler Published: June 16, 2013 Updated: February 11, 2016

Oj supports several different modes. These modes detemine what the JSON output will look like and alternatively what Oj expects when theOj.load()method is called. Mixing the output and input mode formats will most likely not behave as intended. If the object mode is used for producing JSON then use object mode for reading. The same is true for each mode. It is possible to mix but only for advanced users.

Object Mode

Object mode is for fast Ruby object serialization and deserialization. That was the primary purpose of Oj when it was first developed. As such it is the default mode unless changed in the Oj default options. In :object mode Oj generates JSON that follows conventions which allow Class and other information such as Object IDs for circular reference detection to be encoded in a JSON document. The formatting follows these rules.

  1. JSON native types, true, false, nil, String, Hash, Array, and Number are encoded normally.
  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.
  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. 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'"^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"}'.'"^O"'is the same except that it is for built in or odd classes that don't obey the normal Ruby rules. Examples are Rational, Date, and DateTime.
  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 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]}'.
  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. 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]'.

Compat Mode

Compat mode is intended to be as compatible as reasonably possible with the build in Ruby JSON module. The compat mode is generall simplier than the object mode but there are a few things to keep in mind that could cause unexpected problems.

The Ruby JSON module introduces thecreate_id to allow Ruby objects to provide their own serial and deserialize routines. This will place an element in the JSON output, typically under the 'json_class' key. Changing the create_id value will cause the loading of a generated file to not create the expected Ruby object on load.

There are multiple options such as max_nesting, allow_nan, quirks_mode, as well as syntactic options that can be used to create invalid JSON. Use them with care and check the output. Oj supports most of those options.

Strict Mode

Strict mode is follows the JSON specifications and only supports the JSON native types, true, false, nil, String, Hash, Array, and Number are encoded as expected. Encountering any other type cause an Exception to be raised. This is the safest mode as it is just simple translation, no code outside Oj or the core Ruby is execution on loading.

Null Mode

Null mode is similar to strict mode except that a JSON null is inserted if a non-native type is encountered nstead of raising an Exception.