class Yajl::Encoder - yajl-ruby-1.2.1 Documentation

# class Yajl::Encoder

This class contains methods for encoding a Ruby object into JSON, streaming it's output into an IO object. The IO object need only respond to write(str) The JSON stream created is written to the IO in chunks, as it's being created.

### Public Class Methods

enable_json_gem_compatability click to toggle source

Enables the JSON gem compatibility API

    static VALUE rb_yajl_encoder_enable_json_gem_ext(VALUE klass) {
        rb_define_method(rb_cHash, "to_json", rb_yajl_json_ext_hash_to_json, -1);
        rb_define_method(rb_cArray, "to_json", rb_yajl_json_ext_array_to_json, -1);
        rb_define_method(rb_cFixnum, "to_json", rb_yajl_json_ext_fixnum_to_json, -1);
        rb_define_method(rb_cFloat, "to_json", rb_yajl_json_ext_float_to_json, -1);
        rb_define_method(rb_cString, "to_json", rb_yajl_json_ext_string_to_json, -1);
        rb_define_method(rb_cTrueClass, "to_json", rb_yajl_json_ext_true_to_json, -1);
        rb_define_method(rb_cFalseClass, "to_json", rb_yajl_json_ext_false_to_json, -1);
        rb_define_method(rb_cNilClass, "to_json", rb_yajl_json_ext_nil_to_json, -1);
        return Qnil;
    }

encode(obj, *args, &block) click to toggle source

A helper method for encode-and-forget use-cases

Examples:

    Yajl::Encoder.encode(obj[, io, :pretty => true, :indent => "\t", &block])

    output = Yajl::Encoder.encode(obj[, :pretty => true, :indent => "\t", &block])

`obj` is a ruby object to encode to JSON format

`io` is the optional IO stream to encode the ruby object to. If `io` isn't passed, the resulting JSON string is returned. If `io` is passed, nil is returned.

The `options` hash allows you to set two encoding options - :pretty and :indent

:pretty accepts a boolean and will enable/disable “pretty printing” the resulting output

:indent accepts a string and will be used as the indent character(s) during the pretty print process

If a block is passed, it will be used as (and work the same as) the `on_progress` callback

    # File lib/yajl.rb, line 61
    def self.encode(obj, *args, &block)
      # TODO: this code smells, any ideas?
      args.flatten!
      options = {}
      io = nil
      args.each do |arg|
        if arg.is_a?(Hash)
          options = arg
        elsif arg.respond_to?(:write)
          io = arg
        end
      end if args.any?
      new(options).encode(obj, io, &block)
    end

new([:symbolize_keys => true, [:allow_comments => false[, :check_utf8 → false]]]) click to toggle source

:symbolize_keys will turn hash keys into Ruby symbols, defaults to false.

:allow_comments will turn on/off the check for comments inside the JSON stream, defaults to true.

:check_utf8 will validate UTF8 characters found in the JSON stream, defaults to true.

    static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) {
        yajl_encoder_wrapper * wrapper;
        yajl_gen_config cfg;
        VALUE opts, obj, indent;
        unsigned char *indentString = NULL, *actualIndent = NULL;
        int beautify = 0, htmlSafe = 0;

        /* Scan off config vars */
        if (rb_scan_args(argc, argv, "01", &opts) == 1) {
            Check_Type(opts, T_HASH);

            if (rb_hash_aref(opts, sym_pretty) == Qtrue) {
                beautify = 1;
                indent = rb_hash_aref(opts, sym_indent);
                if (indent != Qnil) {
    #ifdef HAVE_RUBY_ENCODING_H
                    indent = rb_str_export_to_enc(indent, utf8Encoding);
    #endif
                    Check_Type(indent, T_STRING);
                    indentString = (unsigned char*)xmalloc(RSTRING_LEN(indent)+1);
                    memcpy(indentString, RSTRING_PTR(indent), RSTRING_LEN(indent));
                    indentString[RSTRING_LEN(indent)] = '\0';
                    actualIndent = indentString;
                }
            }
            if (rb_hash_aref(opts, sym_html_safe) == Qtrue) {
              htmlSafe = 1;
            }
        }
        if (!indentString) {
          indentString = defaultIndentString;
        }
        cfg = (yajl_gen_config){beautify, (const char *)indentString, htmlSafe};

        obj = Data_Make_Struct(klass, yajl_encoder_wrapper, yajl_encoder_wrapper_mark, yajl_encoder_wrapper_free, wrapper);
        wrapper->indentString = actualIndent;
        wrapper->encoder = yajl_gen_alloc(&cfg, NULL);
        wrapper->on_progress_callback = Qnil;
        if (opts != Qnil && rb_funcall(opts, intern_has_key, 1, sym_terminator) == Qtrue) {
            wrapper->terminator = rb_hash_aref(opts, sym_terminator);
    #ifdef HAVE_RUBY_ENCODING_H
            if (TYPE(wrapper->terminator) == T_STRING) {
                wrapper->terminator = rb_str_export_to_enc(wrapper->terminator, utf8Encoding);
            }
    #endif
        } else {
            wrapper->terminator = 0;
        }
        rb_obj_call_init(obj, 0, 0);
        return obj;
    }

### Public Instance Methods

encode(obj[, io[, &block]]) click to toggle source

`obj` is the Ruby object to encode to JSON

`io` is an optional IO used to stream the encoded JSON string to. If `io` isn't specified, this method will return the resulting JSON string. If `io` is specified, this method returns nil

If an optional block is passed, it's called when encoding is complete and passed the resulting JSON string

It should be noted that you can reuse an instance of this class to continue encoding multiple JSON to the same stream. Just continue calling this method, passing it the same IO object with new/different ruby objects to encode. This is how streaming is accomplished.

    static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) {
        yajl_encoder_wrapper * wrapper;
        const unsigned char * buffer;
        unsigned int len;
        VALUE obj, io, blk, outBuff;

        GetEncoder(self, wrapper);

        rb_scan_args(argc, argv, "11&", &obj, &io, &blk);

        if (blk != Qnil) {
            wrapper->on_progress_callback = blk;
        }

        /* begin encode process */
        yajl_encode_part(wrapper, obj, io);

        /* just make sure we output the remaining buffer */
        yajl_gen_get_buf(wrapper->encoder, &buffer, &len);
        outBuff = rb_str_new((const char *)buffer, len);
    #ifdef HAVE_RUBY_ENCODING_H
        rb_enc_associate(outBuff, utf8Encoding);
    #endif
        yajl_gen_clear(wrapper->encoder);

        if (io != Qnil) {
            rb_io_write(io, outBuff);
            if (wrapper->terminator != 0 && wrapper->terminator != Qnil) {
                rb_io_write(io, wrapper->terminator);
            }
            return Qnil;
        } else if (blk != Qnil) {
            rb_funcall(blk, intern_call, 1, outBuff);
            if (wrapper->terminator != 0) {
                rb_funcall(blk, intern_call, 1, wrapper->terminator);
            }
            return Qnil;
        } else {
            if (wrapper->terminator != 0 && wrapper->terminator != Qnil) {
                rb_str_concat(outBuff, wrapper->terminator);
            }
            return outBuff;
        }
        return Qnil;
    }

on_progress = Proc.new {|str| ...} click to toggle source

This callback setter allows you to pass a Proc/lambda or any other object that responds to call.

It will pass the caller a chunk of the encode buffer after it's reached it's internal max buffer size (defaults to 8kb). For example, encoding a large object that would normally result in 24288 bytes of data will result in 3 calls to this callback (assuming the 8kb default encode buffer).

    static VALUE rb_yajl_encoder_set_progress_cb(VALUE self, VALUE callback) {
        yajl_encoder_wrapper * wrapper;
        GetEncoder(self, wrapper);
        wrapper->on_progress_callback = callback;
        return Qnil;
    }