oj 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +17 -23
- data/README.md +74 -425
- data/ext/oj/buf.h +103 -0
- data/ext/oj/cache8.c +4 -0
- data/ext/oj/circarray.c +68 -0
- data/ext/oj/circarray.h +23 -0
- data/ext/oj/code.c +227 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +243 -0
- data/ext/oj/custom.c +1097 -0
- data/ext/oj/dump.c +766 -1534
- data/ext/oj/dump.h +92 -0
- data/ext/oj/dump_compat.c +937 -0
- data/ext/oj/dump_leaf.c +254 -0
- data/ext/oj/dump_object.c +810 -0
- data/ext/oj/dump_rails.c +329 -0
- data/ext/oj/dump_strict.c +416 -0
- data/ext/oj/encode.h +51 -0
- data/ext/oj/err.c +57 -0
- data/ext/oj/err.h +70 -0
- data/ext/oj/extconf.rb +17 -7
- data/ext/oj/fast.c +213 -180
- data/ext/oj/hash.c +163 -0
- data/ext/oj/hash.h +46 -0
- data/ext/oj/hash_test.c +512 -0
- data/ext/oj/mimic_json.c +817 -0
- data/ext/oj/mimic_rails.c +806 -0
- data/ext/oj/mimic_rails.h +17 -0
- data/ext/oj/object.c +752 -0
- data/ext/oj/odd.c +230 -0
- data/ext/oj/odd.h +44 -0
- data/ext/oj/oj.c +1288 -929
- data/ext/oj/oj.h +240 -69
- data/ext/oj/parse.c +1014 -0
- data/ext/oj/parse.h +92 -0
- data/ext/oj/reader.c +223 -0
- data/ext/oj/reader.h +151 -0
- data/ext/oj/resolve.c +127 -0
- data/ext/oj/{cache.h → resolve.h} +6 -13
- data/ext/oj/rxclass.c +133 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +77 -175
- data/ext/oj/scp.c +224 -0
- data/ext/oj/sparse.c +911 -0
- data/ext/oj/stream_writer.c +301 -0
- data/ext/oj/strict.c +162 -0
- data/ext/oj/string_writer.c +480 -0
- data/ext/oj/val_stack.c +98 -0
- data/ext/oj/val_stack.h +188 -0
- data/lib/oj/active_support_helper.rb +41 -0
- data/lib/oj/bag.rb +6 -10
- data/lib/oj/easy_hash.rb +52 -0
- data/lib/oj/json.rb +172 -0
- data/lib/oj/mimic.rb +260 -5
- data/lib/oj/saj.rb +13 -10
- data/lib/oj/schandler.rb +142 -0
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +1 -1
- data/lib/oj.rb +11 -23
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +140 -0
- data/pages/Options.md +250 -0
- data/pages/Rails.md +60 -0
- data/pages/Security.md +20 -0
- data/test/_test_active.rb +76 -0
- data/test/_test_active_mimic.rb +96 -0
- data/test/_test_mimic_rails.rb +126 -0
- data/test/activesupport4/decoding_test.rb +105 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +483 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/helper.rb +27 -0
- data/test/isolated/shared.rb +310 -0
- data/test/isolated/test_mimic_after.rb +13 -0
- data/test/isolated/test_mimic_alone.rb +12 -0
- data/test/isolated/test_mimic_as_json.rb +45 -0
- data/test/isolated/test_mimic_before.rb +13 -0
- data/test/isolated/test_mimic_define.rb +28 -0
- data/test/isolated/test_mimic_rails_after.rb +22 -0
- data/test/isolated/test_mimic_rails_before.rb +21 -0
- data/test/isolated/test_mimic_redefine.rb +15 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +143 -0
- data/test/json_gem/json_encoding_test.rb +109 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/perf_compat.rb +130 -0
- data/test/perf_fast.rb +9 -9
- data/test/perf_file.rb +64 -0
- data/test/{perf_obj.rb → perf_object.rb} +24 -10
- data/test/perf_scp.rb +151 -0
- data/test/perf_strict.rb +32 -113
- data/test/sample.rb +2 -3
- data/test/test_compat.rb +474 -0
- data/test/test_custom.rb +355 -0
- data/test/test_debian.rb +53 -0
- data/test/test_fast.rb +66 -16
- data/test/test_file.rb +237 -0
- data/test/test_gc.rb +49 -0
- data/test/test_hash.rb +29 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +1010 -0
- data/test/test_saj.rb +16 -16
- data/test/test_scp.rb +417 -0
- data/test/test_strict.rb +410 -0
- data/test/test_various.rb +815 -0
- data/test/test_writer.rb +308 -0
- data/test/tests.rb +9 -902
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +253 -38
- data/ext/oj/cache.c +0 -148
- data/ext/oj/foo.rb +0 -6
- data/ext/oj/load.c +0 -1049
- data/test/a.rb +0 -38
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
- data/test/test_mimic.rb +0 -208
data/ext/oj/val_stack.h
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
/* val_stack.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#ifndef __OJ_VAL_STACK_H__
|
32
|
+
#define __OJ_VAL_STACK_H__
|
33
|
+
|
34
|
+
#include "ruby.h"
|
35
|
+
#include "odd.h"
|
36
|
+
#include <stdint.h>
|
37
|
+
#if USE_PTHREAD_MUTEX
|
38
|
+
#include <pthread.h>
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#define STACK_INC 64
|
42
|
+
|
43
|
+
typedef enum {
|
44
|
+
NEXT_NONE = 0,
|
45
|
+
NEXT_ARRAY_NEW = 'a',
|
46
|
+
NEXT_ARRAY_ELEMENT = 'e',
|
47
|
+
NEXT_ARRAY_COMMA = ',',
|
48
|
+
NEXT_HASH_NEW = 'h',
|
49
|
+
NEXT_HASH_KEY = 'k',
|
50
|
+
NEXT_HASH_COLON = ':',
|
51
|
+
NEXT_HASH_VALUE = 'v',
|
52
|
+
NEXT_HASH_COMMA = 'n',
|
53
|
+
} ValNext;
|
54
|
+
|
55
|
+
typedef struct _Val {
|
56
|
+
volatile VALUE val;
|
57
|
+
const char *key;
|
58
|
+
char karray[32];
|
59
|
+
volatile VALUE key_val;
|
60
|
+
union {
|
61
|
+
struct {
|
62
|
+
const char *classname;
|
63
|
+
VALUE clas;
|
64
|
+
};
|
65
|
+
OddArgs odd_args;
|
66
|
+
};
|
67
|
+
uint16_t klen;
|
68
|
+
uint16_t clen;
|
69
|
+
char next; // ValNext
|
70
|
+
char k1; // first original character in the key
|
71
|
+
char kalloc;
|
72
|
+
} *Val;
|
73
|
+
|
74
|
+
typedef struct _ValStack {
|
75
|
+
struct _Val base[STACK_INC];
|
76
|
+
Val head; // current stack
|
77
|
+
Val end; // stack end
|
78
|
+
Val tail; // pointer to one past last element name on stack
|
79
|
+
#if USE_PTHREAD_MUTEX
|
80
|
+
pthread_mutex_t mutex;
|
81
|
+
#elif USE_RB_MUTEX
|
82
|
+
VALUE mutex;
|
83
|
+
#endif
|
84
|
+
|
85
|
+
} *ValStack;
|
86
|
+
|
87
|
+
extern VALUE oj_stack_init(ValStack stack);
|
88
|
+
|
89
|
+
inline static int
|
90
|
+
stack_empty(ValStack stack) {
|
91
|
+
return (stack->head == stack->tail);
|
92
|
+
}
|
93
|
+
|
94
|
+
inline static void
|
95
|
+
stack_cleanup(ValStack stack) {
|
96
|
+
if (stack->base != stack->head) {
|
97
|
+
xfree(stack->head);
|
98
|
+
stack->head = NULL;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
inline static void
|
103
|
+
stack_push(ValStack stack, VALUE val, ValNext next) {
|
104
|
+
if (stack->end <= stack->tail) {
|
105
|
+
size_t len = stack->end - stack->head;
|
106
|
+
size_t toff = stack->tail - stack->head;
|
107
|
+
Val head = stack->head;
|
108
|
+
|
109
|
+
// A realloc can trigger a GC so make sure it happens outside the lock
|
110
|
+
// but lock before changing pointers.
|
111
|
+
if (stack->base == stack->head) {
|
112
|
+
head = ALLOC_N(struct _Val, len + STACK_INC);
|
113
|
+
memcpy(head, stack->base, sizeof(struct _Val) * len);
|
114
|
+
} else {
|
115
|
+
REALLOC_N(head, struct _Val, len + STACK_INC);
|
116
|
+
}
|
117
|
+
#if USE_PTHREAD_MUTEX
|
118
|
+
pthread_mutex_lock(&stack->mutex);
|
119
|
+
#elif USE_RB_MUTEX
|
120
|
+
rb_mutex_lock(stack->mutex);
|
121
|
+
#endif
|
122
|
+
stack->head = head;
|
123
|
+
stack->tail = stack->head + toff;
|
124
|
+
stack->end = stack->head + len + STACK_INC;
|
125
|
+
#if USE_PTHREAD_MUTEX
|
126
|
+
pthread_mutex_unlock(&stack->mutex);
|
127
|
+
#elif USE_RB_MUTEX
|
128
|
+
rb_mutex_unlock(stack->mutex);
|
129
|
+
#endif
|
130
|
+
}
|
131
|
+
stack->tail->val = val;
|
132
|
+
stack->tail->next = next;
|
133
|
+
stack->tail->classname = NULL;
|
134
|
+
stack->tail->clas = Qundef;
|
135
|
+
stack->tail->key = 0;
|
136
|
+
stack->tail->key_val = Qundef;
|
137
|
+
stack->tail->clen = 0;
|
138
|
+
stack->tail->klen = 0;
|
139
|
+
stack->tail->kalloc = 0;
|
140
|
+
stack->tail++;
|
141
|
+
}
|
142
|
+
|
143
|
+
inline static size_t
|
144
|
+
stack_size(ValStack stack) {
|
145
|
+
return stack->tail - stack->head;
|
146
|
+
}
|
147
|
+
|
148
|
+
inline static Val
|
149
|
+
stack_peek(ValStack stack) {
|
150
|
+
if (stack->head < stack->tail) {
|
151
|
+
return stack->tail - 1;
|
152
|
+
}
|
153
|
+
return 0;
|
154
|
+
}
|
155
|
+
|
156
|
+
inline static Val
|
157
|
+
stack_peek_up(ValStack stack) {
|
158
|
+
if (stack->head < stack->tail - 1) {
|
159
|
+
return stack->tail - 2;
|
160
|
+
}
|
161
|
+
return 0;
|
162
|
+
}
|
163
|
+
|
164
|
+
inline static Val
|
165
|
+
stack_prev(ValStack stack) {
|
166
|
+
return stack->tail;
|
167
|
+
}
|
168
|
+
|
169
|
+
inline static VALUE
|
170
|
+
stack_head_val(ValStack stack) {
|
171
|
+
if (Qundef != stack->head->val) {
|
172
|
+
return stack->head->val;
|
173
|
+
}
|
174
|
+
return Qnil;
|
175
|
+
}
|
176
|
+
|
177
|
+
inline static Val
|
178
|
+
stack_pop(ValStack stack) {
|
179
|
+
if (stack->head < stack->tail) {
|
180
|
+
stack->tail--;
|
181
|
+
return stack->tail;
|
182
|
+
}
|
183
|
+
return 0;
|
184
|
+
}
|
185
|
+
|
186
|
+
extern const char* oj_stack_next_string(ValNext n);
|
187
|
+
|
188
|
+
#endif /* __OJ_VAL_STACK_H__ */
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require 'active_support/time'
|
3
|
+
|
4
|
+
module Oj
|
5
|
+
|
6
|
+
# Exists only to handle the ActiveSupport::TimeWithZone.
|
7
|
+
class ActiveSupportHelper
|
8
|
+
|
9
|
+
def self.createTimeWithZone(utc, zone)
|
10
|
+
ActiveSupport::TimeWithZone.new(utc - utc.gmt_offset, ActiveSupport::TimeZone[zone])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
Oj.register_odd(ActiveSupport::TimeWithZone, Oj::ActiveSupportHelper, :createTimeWithZone, :utc, 'time_zone.name')
|
17
|
+
|
18
|
+
# This is a hack to work around an oddness with DateTime and the ActiveSupport
|
19
|
+
# that causes a hang when some methods are called from C. Hour, min(ute),
|
20
|
+
# sec(ond) and other methods are special but they can be called from C until
|
21
|
+
# activesupport/time is required. After that they can not be even though
|
22
|
+
# resond_to? returns true. By defining methods to call super the problem goes
|
23
|
+
# away. There is obviously some magic going on under the covers that I don't
|
24
|
+
# understand.
|
25
|
+
class DateTime
|
26
|
+
def hour()
|
27
|
+
super
|
28
|
+
end
|
29
|
+
def min()
|
30
|
+
super
|
31
|
+
end
|
32
|
+
def sec()
|
33
|
+
super
|
34
|
+
end
|
35
|
+
def sec_fraction()
|
36
|
+
super
|
37
|
+
end
|
38
|
+
def offset()
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
data/lib/oj/bag.rb
CHANGED
@@ -13,7 +13,7 @@ module Oj
|
|
13
13
|
# value. This is intended for testing purposes only.
|
14
14
|
# @example Oj::Bag.new(:@x => 42, :@y => 57)
|
15
15
|
# @param [Hash] args instance variable symbols and their values
|
16
|
-
def initialize(args={
|
16
|
+
def initialize(args = {})
|
17
17
|
args.each do |k,v|
|
18
18
|
self.instance_variable_set(k, v)
|
19
19
|
end
|
@@ -25,8 +25,7 @@ module Oj
|
|
25
25
|
# variable reader, otherwise false.
|
26
26
|
def respond_to?(m)
|
27
27
|
return true if super
|
28
|
-
|
29
|
-
instance_variables.include?(at_m)
|
28
|
+
instance_variables.include?(:"@#{m}")
|
30
29
|
end
|
31
30
|
|
32
31
|
# Handles requests for variable values. Others cause an Exception to be
|
@@ -37,7 +36,7 @@ module Oj
|
|
37
36
|
# @raise [NoMethodError] if the instance variable is not defined.
|
38
37
|
def method_missing(m, *args, &block)
|
39
38
|
raise ArgumentError.new("wrong number of arguments (#{args.size} for 0) to method #{m}") unless args.nil? or args.empty?
|
40
|
-
at_m =
|
39
|
+
at_m = :"@#{m}"
|
41
40
|
raise NoMethodError.new("undefined method #{m}", m) unless instance_variable_defined?(at_m)
|
42
41
|
instance_variable_get(at_m)
|
43
42
|
end
|
@@ -50,13 +49,10 @@ module Oj
|
|
50
49
|
ova = other.instance_variables
|
51
50
|
iv = instance_variables
|
52
51
|
return false if ova.size != iv.size
|
53
|
-
iv.
|
54
|
-
return false if instance_variable_get(vid) != other.instance_variable_get(vid)
|
55
|
-
end
|
56
|
-
true
|
52
|
+
iv.all? { |vid| instance_variable_get(vid) != other.instance_variable_get(vid) }
|
57
53
|
end
|
58
54
|
alias == eql?
|
59
|
-
|
55
|
+
|
60
56
|
# Define a new class based on the Oj::Bag class. This is used internally in
|
61
57
|
# the Oj module and is available to service wrappers that receive XML
|
62
58
|
# requests that include Objects of Classes not defined in the storage
|
@@ -66,7 +62,7 @@ module Oj
|
|
66
62
|
# @raise [NameError] if the classname is invalid.
|
67
63
|
def self.define_class(classname)
|
68
64
|
classname = classname.to_s unless classname.is_a?(String)
|
69
|
-
tokens = classname.split('::').map
|
65
|
+
tokens = classname.split('::').map(&:to_sym)
|
70
66
|
raise NameError.new("Invalid classname '#{classname}") if tokens.empty?
|
71
67
|
m = Object
|
72
68
|
tokens[0..-2].each do |sym|
|
data/lib/oj/easy_hash.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
module Oj
|
3
|
+
|
4
|
+
# A Hash subclass that normalizes the hash keys to allow lookup by the
|
5
|
+
# key.to_s or key.to_sym. It also supports looking up hash values by methods
|
6
|
+
# that match the keys.
|
7
|
+
class EasyHash < Hash
|
8
|
+
|
9
|
+
# Initializes the instance to an empty Hash.
|
10
|
+
def initialize()
|
11
|
+
end
|
12
|
+
|
13
|
+
# Replaces the Object.respond_to?() method.
|
14
|
+
# @param [Symbol] m method symbol
|
15
|
+
# @return [Boolean] true for any method that matches an instance
|
16
|
+
# variable reader, otherwise false.
|
17
|
+
def respond_to?(m)
|
18
|
+
return true if super
|
19
|
+
return true if has_key?(key)
|
20
|
+
return true if has_key?(key.to_s)
|
21
|
+
has_key?(key.to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
return fetch(key, nil) if has_key?(key)
|
26
|
+
return fetch(key.to_s, nil) if has_key?(key.to_s)
|
27
|
+
fetch(key.to_sym, nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Handles requests for Hash values. Others cause an Exception to be raised.
|
31
|
+
# @param [Symbol|String] m method symbol
|
32
|
+
# @return [Boolean] the value of the specified instance variable.
|
33
|
+
# @raise [ArgumentError] if an argument is given. Zero arguments expected.
|
34
|
+
# @raise [NoMethodError] if the instance variable is not defined.
|
35
|
+
def method_missing(m, *args, &block)
|
36
|
+
if m.to_s.end_with?('=')
|
37
|
+
raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
|
38
|
+
m = m[0..-2]
|
39
|
+
return store(m.to_s, args[0]) if has_key?(m.to_s)
|
40
|
+
return store(m.to_sym, args[0]) if has_key?(m.to_sym)
|
41
|
+
return store(m, args[0])
|
42
|
+
else
|
43
|
+
raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
|
44
|
+
return fetch(m, nil) if has_key?(m)
|
45
|
+
return fetch(m.to_s, nil) if has_key?(m.to_s)
|
46
|
+
return fetch(m.to_sym, nil) if has_key?(m.to_sym)
|
47
|
+
end
|
48
|
+
raise NoMethodError.new("undefined method #{m}", m)
|
49
|
+
end
|
50
|
+
|
51
|
+
end # EasyHash
|
52
|
+
end # Oj
|
data/lib/oj/json.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
|
2
|
+
require 'ostruct'
|
3
|
+
require 'oj/state'
|
4
|
+
|
5
|
+
module JSON
|
6
|
+
NaN = 0.0/0.0 unless defined?(::JSON::NaN)
|
7
|
+
Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
|
8
|
+
MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
|
9
|
+
# Taken from the unit test. Note that items like check_circular? are not
|
10
|
+
# present.
|
11
|
+
PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
12
|
+
:allow_nan => false,
|
13
|
+
:array_nl => "\n",
|
14
|
+
:ascii_only => false,
|
15
|
+
:buffer_initial_length => 1024,
|
16
|
+
:depth => 0,
|
17
|
+
:indent => " ",
|
18
|
+
:max_nesting => 100,
|
19
|
+
:object_nl => "\n",
|
20
|
+
:space => " ",
|
21
|
+
:space_before => "",
|
22
|
+
}) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
|
23
|
+
SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
24
|
+
:allow_nan => false,
|
25
|
+
:array_nl => "",
|
26
|
+
:ascii_only => false,
|
27
|
+
:buffer_initial_length => 1024,
|
28
|
+
:depth => 0,
|
29
|
+
:indent => "",
|
30
|
+
:max_nesting => 100,
|
31
|
+
:object_nl => "",
|
32
|
+
:space => "",
|
33
|
+
:space_before => "",
|
34
|
+
}) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
|
35
|
+
FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
36
|
+
:allow_nan => false,
|
37
|
+
:array_nl => "",
|
38
|
+
:ascii_only => false,
|
39
|
+
:buffer_initial_length => 1024,
|
40
|
+
:depth => 0,
|
41
|
+
:indent => "",
|
42
|
+
:max_nesting => 0,
|
43
|
+
:object_nl => "",
|
44
|
+
:space => "",
|
45
|
+
:space_before => "",
|
46
|
+
}) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
|
47
|
+
|
48
|
+
def self.dump_default_options
|
49
|
+
Oj::MimicDumpOption.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.dump_default_options=(h)
|
53
|
+
m = Oj::MimicDumpOption.new
|
54
|
+
h.each do |k,v|
|
55
|
+
m[k] = v
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parser=(p)
|
60
|
+
@@parser = p
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.parser()
|
64
|
+
@@parser
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.generator=(g)
|
68
|
+
@@generator = g
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.generator()
|
72
|
+
@@generator
|
73
|
+
end
|
74
|
+
|
75
|
+
module Ext
|
76
|
+
class Parser
|
77
|
+
def initialize(src)
|
78
|
+
raise TypeError.new("already initialized") unless @source.nil?
|
79
|
+
@source = src
|
80
|
+
end
|
81
|
+
|
82
|
+
def source()
|
83
|
+
raise TypeError.new("already initialized") if @source.nil?
|
84
|
+
@source
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse()
|
88
|
+
raise TypeError.new("already initialized") if @source.nil?
|
89
|
+
JSON.parse(@source)
|
90
|
+
end
|
91
|
+
|
92
|
+
end # Parser
|
93
|
+
end # Ext
|
94
|
+
|
95
|
+
State = ::JSON::Ext::Generator::State
|
96
|
+
|
97
|
+
Parser = ::JSON::Ext::Parser
|
98
|
+
self.parser = ::JSON::Ext::Parser
|
99
|
+
self.generator = ::JSON::Ext::Generator
|
100
|
+
|
101
|
+
# Taken directly from the json gem. Shamelessly copied. It is similar in
|
102
|
+
# some ways to the Oj::Bag class or the Oj::EasyHash class.
|
103
|
+
class GenericObject < OpenStruct
|
104
|
+
class << self
|
105
|
+
alias [] new
|
106
|
+
|
107
|
+
def json_creatable?
|
108
|
+
@json_creatable
|
109
|
+
end
|
110
|
+
|
111
|
+
attr_writer :json_creatable
|
112
|
+
|
113
|
+
def json_create(data)
|
114
|
+
data = data.dup
|
115
|
+
data.delete JSON.create_id
|
116
|
+
self[data]
|
117
|
+
end
|
118
|
+
|
119
|
+
def from_hash(object)
|
120
|
+
case
|
121
|
+
when object.respond_to?(:to_hash)
|
122
|
+
result = new
|
123
|
+
object.to_hash.each do |key, value|
|
124
|
+
result[key] = from_hash(value)
|
125
|
+
end
|
126
|
+
result
|
127
|
+
when object.respond_to?(:to_ary)
|
128
|
+
object.to_ary.map { |a| from_hash(a) }
|
129
|
+
else
|
130
|
+
object
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def load(source, proc = nil, opts = {})
|
135
|
+
result = ::JSON.load(source, proc, opts.merge(:object_class => self))
|
136
|
+
result.nil? ? new : result
|
137
|
+
end
|
138
|
+
|
139
|
+
def dump(obj, *args)
|
140
|
+
::JSON.dump(obj, *args)
|
141
|
+
end
|
142
|
+
|
143
|
+
end # self
|
144
|
+
|
145
|
+
self.json_creatable = false
|
146
|
+
|
147
|
+
def to_hash
|
148
|
+
table
|
149
|
+
end
|
150
|
+
|
151
|
+
def [](name)
|
152
|
+
__send__(name)
|
153
|
+
end unless method_defined?(:[])
|
154
|
+
|
155
|
+
def []=(name, value)
|
156
|
+
__send__("#{name}=", value)
|
157
|
+
end unless method_defined?(:[]=)
|
158
|
+
|
159
|
+
def |(other)
|
160
|
+
self.class[other.to_hash.merge(to_hash)]
|
161
|
+
end
|
162
|
+
|
163
|
+
def as_json(*)
|
164
|
+
{ JSON.create_id => self.class.name }.merge to_hash
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_json(*a)
|
168
|
+
as_json.to_json(*a)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end # JSON
|