Class: Yajl::Encoder
- Defined in:
- ext/yajl/yajl_ext.c,
lib/yajl.rb,
ext/yajl/yajl_ext.c
Overview
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.
Class Method Summary collapse
-
.enable_json_gem_compatability ⇒ Object
call-seq: enable_json_gem_compatability.
-
.encode(obj, *args, &block) ⇒ Object
A helper method for encode-and-forget use-cases.
-
.new(*args) ⇒ Object
call-seq: initialize([:pretty => false[, :indent => ‘ ’][, :terminator => “n”]]).
Instance Method Summary collapse
-
#encode(*args) ⇒ Object
call-seq: encode(obj[, io[, &block]]).
-
#initialize(*args) ⇒ Object
constructor
call-seq: initialize([:pretty => false[, :indent => ‘ ’][, :terminator => “n”]]).
-
#on_progress=(callback) ⇒ Object
call-seq: on_progress = Proc.new {|str| …}.
Constructor Details
#initialize(*args) ⇒ Object
call-seq: initialize([:pretty => false[, :indent => ‘ ’][, :terminator => “n”]])
:pretty will enable/disable beautifying or “pretty priting” the output string.
:indent is the character(s) used to indent the output string.
:terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to determine when the last chunk of the current encode is sent. If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used, the encoder will still pass it - I hope that makes sense ;).
1125 1126 1127 |
# File 'ext/yajl/yajl_ext.c', line 1125
static VALUE rb_yajl_encoder_init(int argc, VALUE * argv, VALUE self) {
return self;
}
|
Class Method Details
.enable_json_gem_compatability ⇒ Object
call-seq: enable_json_gem_compatability
Enables the JSON gem compatibility API
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
# File 'ext/yajl/yajl_ext.c', line 1354 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); #ifdef RUBY_INTEGER_UNIFICATION rb_define_method(rb_cInteger, "to_json", rb_yajl_json_ext_fixnum_to_json, -1); #else rb_define_method(rb_cFixnum, "to_json", rb_yajl_json_ext_fixnum_to_json, -1); #endif 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) ⇒ Object
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
68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/yajl.rb', line 68 def self.encode(obj, *args, &block) # TODO: this code smells, any ideas? args.flatten! = {} io = nil args.each do |arg| if arg.is_a?(Hash) = arg elsif arg.respond_to?(:write) io = arg end end if args.any? new().encode(obj, io, &block) end |
.new(*args) ⇒ Object
call-seq: initialize([:pretty => false[, :indent => ‘ ’][, :terminator => “n”]])
:pretty will enable/disable beautifying or “pretty priting” the output string.
:indent is the character(s) used to indent the output string.
:terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to determine when the last chunk of the current encode is sent. If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used, the encoder will still pass it - I hope that makes sense ;).
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 |
# File 'ext/yajl/yajl_ext.c', line 1053
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 (rb_hash_aref(opts, sym_entities) == Qtrue) {
htmlSafe = 2;
}
}
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, &rb_alloc_funcs);
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;
}
|
Instance Method Details
#encode(*args) ⇒ Object
call-seq: encode(obj[, io[, &block]])
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.
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
# File 'ext/yajl/yajl_ext.c', line 1145
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;
yajl_gen_status status;
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 */
status = yajl_gen_get_buf(wrapper->encoder, &buffer, &len);
if (status != yajl_gen_status_ok) {
yajl_raise_encode_error_for_status(status, obj);
}
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=(callback) ⇒ Object
call-seq: on_progress = Proc.new {|str| …}
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).
1206 1207 1208 1209 1210 1211 |
# File 'ext/yajl/yajl_ext.c', line 1206
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;
}
|