oj 1.2.13 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- data/README.md +2 -8
- data/ext/oj/dump.c +54 -1
- data/ext/oj/oj.c +45 -1
- data/ext/oj/oj.h +7 -0
- data/lib/oj/version.rb +1 -1
- data/test/tests.rb +18 -3
- metadata +2 -2
data/README.md
CHANGED
@@ -32,15 +32,9 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
32
32
|
|
33
33
|
## <a name="release">Release Notes</a>
|
34
34
|
|
35
|
-
### Release 1.
|
35
|
+
### Release 1.3.0
|
36
36
|
|
37
|
-
-
|
38
|
-
|
39
|
-
### Release 1.2.12
|
40
|
-
|
41
|
-
- Fixed GC bug in Oj::Doc, the fast parser.
|
42
|
-
|
43
|
-
- Serialization of Exceptions in Ruby 1.8.7 now includes message and backtrace.
|
37
|
+
- Added an option to control the time format output when in :compat mode.
|
44
38
|
|
45
39
|
## <a name="description">Description</a>
|
46
40
|
|
data/ext/oj/dump.c
CHANGED
@@ -82,6 +82,8 @@ static int hash_cb_compat(VALUE key, VALUE value, Out out);
|
|
82
82
|
static int hash_cb_object(VALUE key, VALUE value, Out out);
|
83
83
|
static void dump_hash(VALUE obj, int depth, int mode, Out out);
|
84
84
|
static void dump_time(VALUE obj, Out out);
|
85
|
+
static void dump_ruby_time(VALUE obj, Out out);
|
86
|
+
static void dump_xml_time(VALUE obj, Out out);
|
85
87
|
static void dump_data_comp(VALUE obj, Out out);
|
86
88
|
static void dump_data_obj(VALUE obj, int depth, Out out);
|
87
89
|
static void dump_obj_comp(VALUE obj, int depth, Out out);
|
@@ -945,12 +947,63 @@ dump_time(VALUE obj, Out out) {
|
|
945
947
|
*out->cur = '\0';
|
946
948
|
}
|
947
949
|
|
950
|
+
static void
|
951
|
+
dump_ruby_time(VALUE obj, Out out) {
|
952
|
+
VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
953
|
+
|
954
|
+
dump_cstr(StringValuePtr(rstr), RSTRING_LEN(rstr), 0, 0, out);
|
955
|
+
}
|
956
|
+
|
957
|
+
static void
|
958
|
+
dump_xml_time(VALUE obj, Out out) {
|
959
|
+
char buf[64];
|
960
|
+
struct tm *tm;
|
961
|
+
#if HAS_RB_TIME_TIMESPEC
|
962
|
+
struct timespec ts = rb_time_timespec(obj);
|
963
|
+
time_t sec = ts.tv_sec;
|
964
|
+
long nsec = ts.tv_nsec;
|
965
|
+
#else
|
966
|
+
time_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
967
|
+
#if HAS_NANO_TIME
|
968
|
+
long nsec = NUM2LONG(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
969
|
+
#else
|
970
|
+
long nsec = NUM2LONG(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
|
971
|
+
#endif
|
972
|
+
#endif
|
973
|
+
int tzhour, tzmin;
|
974
|
+
char tzsign = '+';
|
975
|
+
|
976
|
+
if (out->end - out->cur <= 36) {
|
977
|
+
grow(out, 36);
|
978
|
+
}
|
979
|
+
// 2012-01-05T23:58:07.123456000+09:00
|
980
|
+
tm = localtime(&sec);
|
981
|
+
if (0 > tm->tm_gmtoff) {
|
982
|
+
tzsign = '-';
|
983
|
+
tzhour = (int)(tm->tm_gmtoff / -3600);
|
984
|
+
tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60);
|
985
|
+
} else {
|
986
|
+
tzhour = (int)(tm->tm_gmtoff / 3600);
|
987
|
+
tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60);
|
988
|
+
}
|
989
|
+
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d",
|
990
|
+
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
991
|
+
tm->tm_hour, tm->tm_min, tm->tm_sec, nsec,
|
992
|
+
tzsign, tzhour, tzmin);
|
993
|
+
dump_cstr(buf, 35, 0, 0, out);
|
994
|
+
}
|
995
|
+
|
948
996
|
static void
|
949
997
|
dump_data_comp(VALUE obj, Out out) {
|
950
998
|
VALUE clas = rb_obj_class(obj);
|
951
999
|
|
952
1000
|
if (rb_cTime == clas) {
|
953
|
-
|
1001
|
+
switch (out->opts->time_format) {
|
1002
|
+
case RubyTime: dump_ruby_time(obj, out); break;
|
1003
|
+
case XmlTime: dump_xml_time(obj, out); break;
|
1004
|
+
case UnixTime:
|
1005
|
+
default: dump_time(obj, out); break;
|
1006
|
+
}
|
954
1007
|
} else {
|
955
1008
|
VALUE rstr;
|
956
1009
|
|
data/ext/oj/oj.c
CHANGED
@@ -29,7 +29,7 @@
|
|
29
29
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
*/
|
31
31
|
|
32
|
-
#include <pthread.h>
|
32
|
+
#include <pthread.h>
|
33
33
|
#include <stdlib.h>
|
34
34
|
#include <errno.h>
|
35
35
|
#include <stdio.h>
|
@@ -84,8 +84,12 @@ static VALUE max_stack_sym;
|
|
84
84
|
static VALUE mode_sym;
|
85
85
|
static VALUE null_sym;
|
86
86
|
static VALUE object_sym;
|
87
|
+
static VALUE ruby_sym;
|
87
88
|
static VALUE strict_sym;
|
88
89
|
static VALUE symbol_keys_sym;
|
90
|
+
static VALUE time_format_sym;
|
91
|
+
static VALUE unix_sym;
|
92
|
+
static VALUE xmlschema_sym;
|
89
93
|
|
90
94
|
static VALUE array_nl_sym;
|
91
95
|
static VALUE create_additions_sym;
|
@@ -114,6 +118,7 @@ struct _Options oj_default_options = {
|
|
114
118
|
No, // sym_key
|
115
119
|
No, // ascii_only
|
116
120
|
ObjectMode, // mode
|
121
|
+
UnixTime, // time_format
|
117
122
|
json_class, // create_id
|
118
123
|
65536, // max_stack
|
119
124
|
0, // dump_opts
|
@@ -143,6 +148,7 @@ oj_get_odd(VALUE clas) {
|
|
143
148
|
* - auto_define: [true|false|nil] automatically define classes if they do not exist
|
144
149
|
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
|
145
150
|
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
|
151
|
+
* - time_format: [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
|
146
152
|
* - create_id: [String|nil] create id for json compatible object encoding, default is 'json_create'
|
147
153
|
* - max_stack: [Fixnum|nil] maximum json size to allocate on the stack, default is 65536
|
148
154
|
* @return [Hash] all current option settings.
|
@@ -164,6 +170,12 @@ get_def_opts(VALUE self) {
|
|
164
170
|
case ObjectMode:
|
165
171
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
166
172
|
}
|
173
|
+
switch (oj_default_options.time_format) {
|
174
|
+
case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
|
175
|
+
case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
|
176
|
+
case UnixTime:
|
177
|
+
default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
|
178
|
+
}
|
167
179
|
rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
|
168
180
|
|
169
181
|
return opts;
|
@@ -186,6 +198,10 @@ get_def_opts(VALUE self) {
|
|
186
198
|
* and to_json() methods and encodes variables using code internal to
|
187
199
|
* the Oj gem. The :null mode ignores non-supported Objects and
|
188
200
|
* replaces them with a null.
|
201
|
+
* @param [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
|
202
|
+
* :unix decimal number denoting the number of seconds since 1/1/1970,
|
203
|
+
* :xmlschema date-time format taken from XML Schema as a String,
|
204
|
+
* :ruby Time.to_s formatted String
|
189
205
|
* @param [String|nil] :create_id create id for json compatible object encoding
|
190
206
|
* @param [Fixnum|nil] :max_stack maximum size to allocate on the stack for a JSON String
|
191
207
|
* @return [nil]
|
@@ -235,6 +251,19 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
235
251
|
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n");
|
236
252
|
}
|
237
253
|
|
254
|
+
v = rb_hash_lookup(opts, time_format_sym);
|
255
|
+
if (Qnil == v) {
|
256
|
+
// ignore
|
257
|
+
} else if (unix_sym == v) {
|
258
|
+
oj_default_options.time_format = UnixTime;
|
259
|
+
} else if (xmlschema_sym == v) {
|
260
|
+
oj_default_options.time_format = XmlTime;
|
261
|
+
} else if (ruby_sym == v) {
|
262
|
+
oj_default_options.time_format = RubyTime;
|
263
|
+
} else {
|
264
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.\n");
|
265
|
+
}
|
266
|
+
|
238
267
|
if (Qtrue == rb_funcall(opts, rb_intern("has_key?"), 1, create_id_sym)) {
|
239
268
|
if (0 != oj_default_options.create_id) {
|
240
269
|
if (json_class != oj_default_options.create_id) {
|
@@ -301,6 +330,17 @@ parse_options(VALUE ropts, Options copts) {
|
|
301
330
|
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n");
|
302
331
|
}
|
303
332
|
}
|
333
|
+
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
334
|
+
if (unix_sym == v) {
|
335
|
+
copts->time_format = UnixTime;
|
336
|
+
} else if (xmlschema_sym == v) {
|
337
|
+
copts->time_format = XmlTime;
|
338
|
+
} else if (ruby_sym == v) {
|
339
|
+
copts->time_format = RubyTime;
|
340
|
+
} else {
|
341
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.\n");
|
342
|
+
}
|
343
|
+
}
|
304
344
|
for (o = ynos; 0 != o->attr; o++) {
|
305
345
|
if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
|
306
346
|
if (Qtrue == v) {
|
@@ -850,8 +890,12 @@ void Init_oj() {
|
|
850
890
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
851
891
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
852
892
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
893
|
+
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
853
894
|
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
854
895
|
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
|
896
|
+
time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
|
897
|
+
unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
|
898
|
+
xmlschema_sym = ID2SYM(rb_intern("xmlschema")); rb_gc_register_address(&xmlschema_sym);
|
855
899
|
|
856
900
|
oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
|
857
901
|
|
data/ext/oj/oj.h
CHANGED
@@ -80,6 +80,12 @@ typedef enum {
|
|
80
80
|
CompatMode = 'c'
|
81
81
|
} Mode;
|
82
82
|
|
83
|
+
typedef enum {
|
84
|
+
UnixTime = 'u',
|
85
|
+
XmlTime = 'x',
|
86
|
+
RubyTime = 'r'
|
87
|
+
} TimeFormat;
|
88
|
+
|
83
89
|
typedef struct _DumpOpts {
|
84
90
|
const char *indent;
|
85
91
|
const char *before_sep;
|
@@ -100,6 +106,7 @@ typedef struct _Options {
|
|
100
106
|
char sym_key; // YesNo
|
101
107
|
char ascii_only; // YesNo
|
102
108
|
char mode; // Mode
|
109
|
+
char time_format; // TimeFormat
|
103
110
|
const char *create_id; // 0 or string
|
104
111
|
size_t max_stack; // max size to allocate on the stack
|
105
112
|
DumpOpts dump_opts;
|
data/lib/oj/version.rb
CHANGED
data/test/tests.rb
CHANGED
@@ -109,6 +109,7 @@ class Juice < ::Test::Unit::TestCase
|
|
109
109
|
:symbol_keys=>false,
|
110
110
|
:ascii_only=>false,
|
111
111
|
:mode=>:object,
|
112
|
+
:time_format=>:unix,
|
112
113
|
:max_stack=>65536,
|
113
114
|
:create_id=>'json_class'}, opts)
|
114
115
|
end
|
@@ -121,6 +122,7 @@ class Juice < ::Test::Unit::TestCase
|
|
121
122
|
:symbol_keys=>false,
|
122
123
|
:ascii_only=>false,
|
123
124
|
:mode=>:object,
|
125
|
+
:time_format=>:unix,
|
124
126
|
:max_stack=>65536,
|
125
127
|
:create_id=>'json_class'}
|
126
128
|
o2 = {
|
@@ -130,6 +132,7 @@ class Juice < ::Test::Unit::TestCase
|
|
130
132
|
:symbol_keys=>true,
|
131
133
|
:ascii_only=>true,
|
132
134
|
:mode=>:compat,
|
135
|
+
:time_format=>:ruby,
|
133
136
|
:max_stack=>4000,
|
134
137
|
:create_id=>nil}
|
135
138
|
o3 = { :indent => 4 }
|
@@ -250,10 +253,22 @@ class Juice < ::Test::Unit::TestCase
|
|
250
253
|
json = Oj.dump(t, :mode => :null)
|
251
254
|
assert_equal('null', json)
|
252
255
|
end
|
253
|
-
def
|
254
|
-
t = Time.
|
256
|
+
def test_unix_time_compat
|
257
|
+
t = Time.xmlschema("2012-01-05T23:58:07.123456000+09:00")
|
258
|
+
#t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
|
255
259
|
json = Oj.dump(t, :mode => :compat)
|
256
|
-
assert_equal(%{1325775487.
|
260
|
+
assert_equal(%{1325775487.123456000}, json)
|
261
|
+
end
|
262
|
+
def test_ruby_time_compat
|
263
|
+
t = Time.xmlschema("2012-01-05T23:58:07.123456000+09:00")
|
264
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :ruby)
|
265
|
+
#assert_equal(%{"2012-01-05 23:58:07 +0900"}, json)
|
266
|
+
assert_equal(%{"#{t.to_s}"}, json)
|
267
|
+
end
|
268
|
+
def test_xml_time_compat
|
269
|
+
t = Time.xmlschema("2012-01-05T23:58:07.123456000+09:00")
|
270
|
+
json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
|
271
|
+
assert_equal(%{"2012-01-05T23:58:07.123456000+09:00"}, json)
|
257
272
|
end
|
258
273
|
def test_time_object
|
259
274
|
t = Time.now()
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The fastest JSON parser and object serializer. '
|
15
15
|
email: peter@ohler.com
|