jrjackson 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{.jrubyrc → .__jrubyrc} +2 -2
- data/.gitignore +5 -0
- data/Gemfile +1 -0
- data/alt_bench.rb +46 -0
- data/dependency-reduced-pom.xml +6 -5
- data/lib/jrjackson/build_info.rb +2 -2
- data/lib/jrjackson/jars/jrjackson-1.2.16.jar +0 -0
- data/lib/jrjackson/jrjackson.rb +38 -13
- data/pom.xml +11 -10
- data/run_all_individual_bench.sh +17 -15
- data/run_jruby_individual_bench.sh +20 -0
- data/run_mri_individual_bench.sh +7 -0
- data/src/main/java/com/jrjackson/IParseHandler.java +53 -0
- data/src/main/java/com/jrjackson/JavaBigDecimalValueConverter.java +17 -0
- data/src/main/java/com/jrjackson/JavaBigIntValueConverter.java +17 -0
- data/src/main/java/com/jrjackson/JavaConverter.java +10 -0
- data/src/main/java/com/jrjackson/JavaFloatValueConverter.java +16 -0
- data/src/main/java/com/jrjackson/JavaHandler.java +118 -0
- data/src/main/java/com/jrjackson/JavaLongValueConverter.java +16 -0
- data/src/main/java/com/jrjackson/JjParse.java +147 -0
- data/src/main/java/com/jrjackson/JrJacksonBase.java +159 -0
- data/src/main/java/com/jrjackson/JrJacksonJava.java +81 -0
- data/src/main/java/com/jrjackson/JrJacksonRaw.java +59 -102
- data/src/main/java/com/jrjackson/JrJacksonRuby.java +117 -0
- data/src/main/java/com/jrjackson/JrJacksonSaj.java +26 -0
- data/src/main/java/com/jrjackson/JrJacksonSch.java +25 -0
- data/src/main/java/com/jrjackson/JrJacksonService.java +15 -0
- data/src/main/java/com/jrjackson/JrParse.java +149 -0
- data/src/main/java/com/jrjackson/RubyAnySerializer.java +112 -55
- data/src/main/java/com/jrjackson/RubyBigDecimalValueConverter.java +18 -0
- data/src/main/java/com/jrjackson/RubyBigIntValueConverter.java +21 -0
- data/src/main/java/com/jrjackson/RubyConverter.java +12 -0
- data/src/main/java/com/jrjackson/RubyDateFormat.java +36 -0
- data/src/main/java/com/jrjackson/RubyFloatValueConverter.java +18 -0
- data/src/main/java/com/jrjackson/RubyHandler.java +119 -0
- data/src/main/java/com/jrjackson/RubyIntValueConverter.java +18 -0
- data/src/main/java/com/jrjackson/RubyJacksonModule.java +40 -38
- data/src/main/java/com/jrjackson/RubyNameConverter.java +9 -0
- data/src/main/java/com/jrjackson/RubyObjectDeserializer.java +24 -33
- data/src/main/java/com/jrjackson/RubyStringConverter.java +1 -2
- data/src/main/java/com/jrjackson/{RubySymbolConverter.java → RubyStringKeyConverter.java} +3 -2
- data/src/main/java/com/jrjackson/RubyStringNameConverter.java +12 -0
- data/src/main/java/com/jrjackson/RubySymbolKeyConverter.java +15 -0
- data/src/main/java/com/jrjackson/RubySymbolNameConverter.java +12 -0
- data/src/main/java/com/jrjackson/RubyUtils.java +40 -1
- data/src/main/java/com/jrjackson/SajParse.java +169 -0
- data/src/main/java/com/jrjackson/SchParse.java +209 -0
- data/src/main/java/com/jrjackson/StreamParse.java +66 -0
- data/test/jrjackson_test.rb +271 -6
- metadata +49 -17
- data/src/test/java/com/jrjackson/jruby/AppTest.java +0 -38
@@ -0,0 +1,117 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.JsonFactory;
|
4
|
+
import com.fasterxml.jackson.core.JsonParser;
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyClass;
|
7
|
+
import org.jruby.anno.JRubyModule;
|
8
|
+
import org.jruby.anno.JRubyMethod;
|
9
|
+
import org.jruby.runtime.ThreadContext;
|
10
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
+
|
12
|
+
import java.io.IOException;
|
13
|
+
|
14
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
15
|
+
import com.fasterxml.jackson.core.JsonProcessingException;
|
16
|
+
import static com.jrjackson.JrJacksonBase.flagged;
|
17
|
+
import org.jruby.RubyHash;
|
18
|
+
import org.jruby.exceptions.RaiseException;
|
19
|
+
|
20
|
+
@JRubyModule(name = "JrJacksonRuby")
|
21
|
+
public class JrJacksonRuby extends JrJacksonBase {
|
22
|
+
|
23
|
+
public JrJacksonRuby(Ruby ruby, RubyClass metaclass) {
|
24
|
+
super(ruby, metaclass);
|
25
|
+
}
|
26
|
+
|
27
|
+
// deserialize
|
28
|
+
@JRubyMethod(module = true, name = {"parse_sym", "load_sym"}, required = 2)
|
29
|
+
public static Object parse_sym(ThreadContext context, IRubyObject self, IRubyObject arg, IRubyObject opts)
|
30
|
+
throws JsonProcessingException, IOException, RaiseException {
|
31
|
+
|
32
|
+
return __parse(context, arg,
|
33
|
+
new RubySymbolNameConverter(),
|
34
|
+
new RubyBigIntValueConverter(),
|
35
|
+
new RubyBigDecimalValueConverter()
|
36
|
+
);
|
37
|
+
}
|
38
|
+
|
39
|
+
@JRubyMethod(module = true, name = {"parse", "load"}, required = 2)
|
40
|
+
public static Object parse(ThreadContext context, IRubyObject self, IRubyObject arg, IRubyObject opts)
|
41
|
+
throws JsonProcessingException, IOException, RaiseException {
|
42
|
+
|
43
|
+
RubyNameConverter konv = new RubyStringNameConverter();
|
44
|
+
RubyConverter ikonv = new RubyBigIntValueConverter();
|
45
|
+
RubyConverter dkonv = new RubyBigDecimalValueConverter();
|
46
|
+
if (opts != context.nil) {
|
47
|
+
RubyHash options = opts.convertToHash();
|
48
|
+
if (options.size() > 0) {
|
49
|
+
if (flagged(options,
|
50
|
+
RubyUtils.rubySymbol(context.runtime, "symbolize_keys"))) {
|
51
|
+
konv = new RubySymbolNameConverter();
|
52
|
+
}
|
53
|
+
if (!flagged(options,
|
54
|
+
RubyUtils.rubySymbol(context.runtime, "use_bigdecimal"), true)) {
|
55
|
+
dkonv = new RubyFloatValueConverter();
|
56
|
+
}
|
57
|
+
if (flagged(options,
|
58
|
+
RubyUtils.rubySymbol(context.runtime, "use_smallint"))) {
|
59
|
+
ikonv = new RubyIntValueConverter();
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return __parse(context, arg, konv, ikonv, dkonv);
|
64
|
+
}
|
65
|
+
|
66
|
+
@JRubyMethod(module = true, name = {"compat_parse", "compat_load"}, required = 2)
|
67
|
+
public static Object compat_parse(ThreadContext context, IRubyObject self, IRubyObject arg, IRubyObject opts)
|
68
|
+
throws JsonProcessingException, IOException, RaiseException {
|
69
|
+
RubyKeyConverter konv = new RubyStringKeyConverter();
|
70
|
+
RubyConverter dkonv = new RubyBigDecimalValueConverter();
|
71
|
+
RubyConverter ikonv = new RubyBigIntValueConverter();
|
72
|
+
|
73
|
+
if (opts != context.nil) {
|
74
|
+
RubyHash options = opts.convertToHash();
|
75
|
+
if (options.size() > 0) {
|
76
|
+
if (flagged(options,
|
77
|
+
RubyUtils.rubySymbol(context.runtime, "symbolize_keys"))) {
|
78
|
+
konv = new RubySymbolKeyConverter();
|
79
|
+
}
|
80
|
+
if (!flagged(options,
|
81
|
+
RubyUtils.rubySymbol(context.runtime, "use_bigdecimal"), true)) {
|
82
|
+
dkonv = new RubyFloatValueConverter();
|
83
|
+
}
|
84
|
+
if (flagged(options,
|
85
|
+
RubyUtils.rubySymbol(context.runtime, "use_smallint"))) {
|
86
|
+
ikonv = new RubyIntValueConverter();
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
ObjectMapper om = RubyJacksonModule.mapperWith(context.runtime, konv, ikonv, dkonv);
|
91
|
+
|
92
|
+
return _parse(context, arg, om);
|
93
|
+
}
|
94
|
+
|
95
|
+
private static Object __parse(ThreadContext context, IRubyObject arg,
|
96
|
+
RubyNameConverter keykonv, RubyConverter intconv, RubyConverter decimalconv)
|
97
|
+
throws JsonProcessingException, IOException, RaiseException {
|
98
|
+
|
99
|
+
RubyHandler handler = new RubyHandler(context,
|
100
|
+
keykonv,
|
101
|
+
intconv,
|
102
|
+
decimalconv);
|
103
|
+
JrParse parse = new JrParse(handler);
|
104
|
+
ObjectMapper mapper = RubyJacksonModule.rawBigNumberMapper();
|
105
|
+
JsonFactory jf = mapper.getFactory();
|
106
|
+
JsonParser jp;
|
107
|
+
try {
|
108
|
+
jp = buildParser(context, jf, arg);
|
109
|
+
} catch (IOException e) {
|
110
|
+
throw context.runtime.newIOError(e.getLocalizedMessage());
|
111
|
+
}
|
112
|
+
|
113
|
+
parse.deserialize(jp);
|
114
|
+
jp.close();
|
115
|
+
return handler.getResult();
|
116
|
+
}
|
117
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.RubyClass;
|
5
|
+
import org.jruby.anno.JRubyMethod;
|
6
|
+
import org.jruby.anno.JRubyModule;
|
7
|
+
import org.jruby.runtime.ThreadContext;
|
8
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
9
|
+
|
10
|
+
import org.jruby.exceptions.RaiseException;
|
11
|
+
|
12
|
+
@JRubyModule(name = "JrJacksonSaj")
|
13
|
+
public class JrJacksonSaj extends JrJacksonBase {
|
14
|
+
|
15
|
+
public JrJacksonSaj(Ruby ruby, RubyClass metaclass) {
|
16
|
+
super(ruby, metaclass);
|
17
|
+
}
|
18
|
+
|
19
|
+
// deserialize
|
20
|
+
@JRubyMethod(module = true, name = {"parse", "load"}, required = 3)
|
21
|
+
public static IRubyObject parse(ThreadContext context, IRubyObject self, IRubyObject handler, IRubyObject arg, IRubyObject opts)
|
22
|
+
throws RaiseException {
|
23
|
+
StreamParse sp = new SajParse(context, handler);
|
24
|
+
return _sjcparse(context, handler, arg, opts, sp);
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.RubyClass;
|
5
|
+
import org.jruby.anno.JRubyMethod;
|
6
|
+
import org.jruby.anno.JRubyModule;
|
7
|
+
import org.jruby.runtime.ThreadContext;
|
8
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
9
|
+
import org.jruby.exceptions.RaiseException;
|
10
|
+
|
11
|
+
@JRubyModule(name = "JrJacksonSch")
|
12
|
+
public class JrJacksonSch extends JrJacksonBase {
|
13
|
+
|
14
|
+
public JrJacksonSch(Ruby ruby, RubyClass metaclass) {
|
15
|
+
super(ruby, metaclass);
|
16
|
+
}
|
17
|
+
|
18
|
+
// deserialize
|
19
|
+
@JRubyMethod(module = true, name = {"parse", "load"}, required = 3)
|
20
|
+
public static IRubyObject parse(ThreadContext context, IRubyObject self, IRubyObject handler, IRubyObject arg, IRubyObject opts)
|
21
|
+
throws RaiseException {
|
22
|
+
StreamParse sp = new SchParse(context, handler);
|
23
|
+
return _sjcparse(context, handler, arg, opts, sp);
|
24
|
+
}
|
25
|
+
}
|
@@ -13,9 +13,24 @@ public class JrJacksonService implements BasicLibraryService {
|
|
13
13
|
public boolean basicLoad(final Ruby ruby) throws IOException {
|
14
14
|
RubyModule jr_jackson = ruby.defineModule("JrJackson");
|
15
15
|
|
16
|
+
RubyModule jr_jackson_base = ruby.defineModuleUnder("Base", jr_jackson);
|
17
|
+
jr_jackson_base.defineAnnotatedMethods(JrJacksonBase.class);
|
18
|
+
|
16
19
|
RubyModule jr_jackson_raw = ruby.defineModuleUnder("Raw", jr_jackson);
|
17
20
|
jr_jackson_raw.defineAnnotatedMethods(JrJacksonRaw.class);
|
18
21
|
|
22
|
+
RubyModule jr_jackson_ruby = ruby.defineModuleUnder("Ruby", jr_jackson);
|
23
|
+
jr_jackson_ruby.defineAnnotatedMethods(JrJacksonRuby.class);
|
24
|
+
|
25
|
+
RubyModule jr_jackson_java = ruby.defineModuleUnder("Java", jr_jackson);
|
26
|
+
jr_jackson_java.defineAnnotatedMethods(JrJacksonJava.class);
|
27
|
+
|
28
|
+
RubyModule jr_jackson_saj = ruby.defineModuleUnder("Saj", jr_jackson);
|
29
|
+
jr_jackson_saj.defineAnnotatedMethods(JrJacksonSaj.class);
|
30
|
+
|
31
|
+
RubyModule jr_jackson_sch = ruby.defineModuleUnder("Sch", jr_jackson);
|
32
|
+
jr_jackson_sch.defineAnnotatedMethods(JrJacksonSch.class);
|
33
|
+
|
19
34
|
RubyClass runtimeError = ruby.getRuntimeError();
|
20
35
|
RubyClass parseError = jr_jackson.defineClassUnder("ParseError", runtimeError, runtimeError.getAllocator());
|
21
36
|
return true;
|
@@ -0,0 +1,149 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.JsonParser;
|
4
|
+
import com.fasterxml.jackson.core.JsonProcessingException;
|
5
|
+
import com.fasterxml.jackson.core.JsonStreamContext;
|
6
|
+
import java.io.IOException;
|
7
|
+
import java.util.HashMap;
|
8
|
+
import org.jruby.RubyArray;
|
9
|
+
import org.jruby.RubyHash;
|
10
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
+
|
12
|
+
|
13
|
+
/**
|
14
|
+
*
|
15
|
+
* @author Guy Boertje
|
16
|
+
*/
|
17
|
+
public class JrParse {
|
18
|
+
private final RubyHandler _handler;
|
19
|
+
protected final HashMap<JsonStreamContext, IRubyObject> _objectMap = new HashMap<JsonStreamContext, IRubyObject>();
|
20
|
+
protected JsonStreamContext _deepestContext;
|
21
|
+
|
22
|
+
public JrParse(RubyHandler handler) {
|
23
|
+
_handler = handler;
|
24
|
+
|
25
|
+
}
|
26
|
+
|
27
|
+
public void deserialize(JsonParser jp) throws JsonProcessingException, IOException {
|
28
|
+
try {
|
29
|
+
|
30
|
+
while (jp.nextValue() != null) {
|
31
|
+
handleCurrentToken(jp);
|
32
|
+
}
|
33
|
+
|
34
|
+
} catch (JsonProcessingException e) {
|
35
|
+
_handler.raiseError(e.getLocalizedMessage());
|
36
|
+
} catch (IOException e) {
|
37
|
+
_handler.raiseError(e.getLocalizedMessage());
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
private void callAddValue(JsonStreamContext x) {
|
42
|
+
JsonStreamContext px = x.getParent();
|
43
|
+
IRubyObject dtarget = _objectMap.get(_deepestContext);
|
44
|
+
|
45
|
+
if (px == null) {
|
46
|
+
_handler.addValue(dtarget);
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
|
50
|
+
IRubyObject value = _objectMap.get(x);
|
51
|
+
|
52
|
+
if (x.inArray()) {
|
53
|
+
_handler.arrayAppend(
|
54
|
+
(RubyArray)value, dtarget);
|
55
|
+
} else if (x.inObject()) {
|
56
|
+
_handler.hashSet(
|
57
|
+
(RubyHash)value, callHashKey(x), dtarget);
|
58
|
+
|
59
|
+
} else {
|
60
|
+
_handler.addValue(value);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
private void callAddValue(JsonStreamContext x, IRubyObject val) {
|
65
|
+
|
66
|
+
if (x.inArray()) {
|
67
|
+
RubyArray a = (RubyArray)_objectMap.get(x);
|
68
|
+
_handler.arrayAppend(a, val);
|
69
|
+
} else if (x.inObject()) {
|
70
|
+
RubyHash h = (RubyHash)_objectMap.get(x);
|
71
|
+
_handler.hashSet(h, callHashKey(x), val);
|
72
|
+
|
73
|
+
} else {
|
74
|
+
_handler.addValue(val);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
private IRubyObject callHashKey(JsonStreamContext x) {
|
79
|
+
String k = x.getCurrentName();
|
80
|
+
if (k == null) {
|
81
|
+
return _handler.treatNull();
|
82
|
+
}
|
83
|
+
return _handler.hashKey(k);
|
84
|
+
}
|
85
|
+
|
86
|
+
private void handleCurrentToken(JsonParser jp)
|
87
|
+
throws IOException, JsonProcessingException {
|
88
|
+
|
89
|
+
JsonStreamContext cx = jp.getParsingContext();
|
90
|
+
|
91
|
+
switch (jp.getCurrentToken()) {
|
92
|
+
case START_OBJECT:
|
93
|
+
_deepestContext = cx;
|
94
|
+
_objectMap.put(cx, _handler.hashStart());
|
95
|
+
break;
|
96
|
+
|
97
|
+
case START_ARRAY:
|
98
|
+
_deepestContext = cx;
|
99
|
+
_objectMap.put(cx, _handler.arrayStart());
|
100
|
+
|
101
|
+
case FIELD_NAME:
|
102
|
+
break;
|
103
|
+
|
104
|
+
case VALUE_EMBEDDED_OBJECT:
|
105
|
+
System.out.println("-------- VALUE_EMBEDDED_OBJECT ????????? --------");
|
106
|
+
System.out.println(jp.getEmbeddedObject());
|
107
|
+
break;
|
108
|
+
|
109
|
+
case VALUE_STRING:
|
110
|
+
callAddValue(cx,
|
111
|
+
_handler.treatString(jp));
|
112
|
+
break;
|
113
|
+
|
114
|
+
case VALUE_NUMBER_INT:
|
115
|
+
callAddValue(cx,
|
116
|
+
_handler.treatInt(jp));
|
117
|
+
break;
|
118
|
+
|
119
|
+
case VALUE_NUMBER_FLOAT:
|
120
|
+
callAddValue(cx,
|
121
|
+
_handler.treatFloat(jp));
|
122
|
+
break;
|
123
|
+
|
124
|
+
case VALUE_TRUE:
|
125
|
+
callAddValue(cx, _handler.trueValue());
|
126
|
+
break;
|
127
|
+
|
128
|
+
case VALUE_FALSE:
|
129
|
+
callAddValue(cx, _handler.falseValue());
|
130
|
+
break;
|
131
|
+
|
132
|
+
case VALUE_NULL: // should not get this but...
|
133
|
+
callAddValue(cx, _handler.treatNull());
|
134
|
+
break;
|
135
|
+
|
136
|
+
case END_ARRAY:
|
137
|
+
_handler.arrayEnd();
|
138
|
+
callAddValue(cx);
|
139
|
+
_deepestContext = cx;
|
140
|
+
break;
|
141
|
+
|
142
|
+
case END_OBJECT:
|
143
|
+
_handler.hashEnd();
|
144
|
+
callAddValue(cx);
|
145
|
+
_deepestContext = cx;
|
146
|
+
break;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|
@@ -1,46 +1,43 @@
|
|
1
1
|
package com.jrjackson;
|
2
2
|
|
3
|
-
import
|
4
|
-
import
|
5
|
-
|
6
|
-
import com.fasterxml.jackson.core.*;
|
7
|
-
|
8
|
-
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
3
|
+
import com.fasterxml.jackson.core.JsonGenerationException;
|
4
|
+
import com.fasterxml.jackson.core.JsonGenerator;
|
9
5
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
10
|
-
|
11
6
|
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
12
|
-
import java.math.BigDecimal;
|
13
|
-
import java.math.BigInteger;
|
14
|
-
|
15
|
-
import org.jruby.*;
|
16
7
|
import org.jruby.ext.bigdecimal.RubyBigDecimal;
|
17
|
-
|
8
|
+
|
18
9
|
import org.jruby.internal.runtime.methods.DynamicMethod;
|
10
|
+
import org.jruby.java.proxies.JavaProxy;
|
11
|
+
import org.jruby.runtime.ThreadContext;
|
19
12
|
import org.jruby.runtime.builtin.IRubyObject;
|
20
13
|
|
21
|
-
|
14
|
+
import java.io.IOException;
|
15
|
+
import java.text.DateFormat;
|
16
|
+
import java.text.SimpleDateFormat;
|
17
|
+
import org.jruby.RubyArray;
|
18
|
+
import org.jruby.RubyBignum;
|
19
|
+
import org.jruby.RubyBoolean;
|
20
|
+
import org.jruby.RubyClass;
|
21
|
+
import org.jruby.RubyFixnum;
|
22
|
+
import org.jruby.RubyFloat;
|
23
|
+
import org.jruby.RubyHash;
|
24
|
+
import org.jruby.RubyNumeric;
|
25
|
+
import org.jruby.RubyObject;
|
26
|
+
import org.jruby.RubyString;
|
27
|
+
import org.jruby.RubyStruct;
|
28
|
+
import org.jruby.RubySymbol;
|
29
|
+
import org.jruby.RubyTime;
|
30
|
+
|
31
|
+
public class RubyAnySerializer {
|
22
32
|
|
23
33
|
/**
|
24
|
-
* Singleton instance to use.
|
34
|
+
* Singleton instance to use.""
|
25
35
|
*/
|
26
36
|
public static final RubyAnySerializer instance = new RubyAnySerializer();
|
27
|
-
private static final HashMap<Class, Class> class_maps = new HashMap<Class, Class>();
|
28
|
-
|
29
|
-
static {
|
30
|
-
// not need now - clean up required
|
31
|
-
class_maps.put(RubyBoolean.class, Boolean.class);
|
32
|
-
class_maps.put(RubyFloat.class, Double.class);
|
33
|
-
class_maps.put(RubyFixnum.class, Long.class);
|
34
|
-
class_maps.put(RubyBignum.class, BigInteger.class);
|
35
|
-
class_maps.put(RubyBigDecimal.class, BigDecimal.class);
|
36
|
-
}
|
37
37
|
|
38
38
|
public RubyAnySerializer() {
|
39
|
-
super(IRubyObject.class);
|
40
|
-
}
|
39
|
+
// super(IRubyObject.class);
|
41
40
|
|
42
|
-
private Class<?> rubyJavaClassLookup(Class target) {
|
43
|
-
return class_maps.get(target);
|
44
41
|
}
|
45
42
|
|
46
43
|
private void serializeUnknownRubyObject(ThreadContext ctx, IRubyObject rubyObject, JsonGenerator jgen, SerializerProvider provider)
|
@@ -50,29 +47,39 @@ public class RubyAnySerializer extends StdSerializer<IRubyObject> {
|
|
50
47
|
DynamicMethod method = meta.searchMethod("to_time");
|
51
48
|
if (!method.isUndefined()) {
|
52
49
|
RubyTime dt = (RubyTime) method.call(ctx, rubyObject, meta, "to_time");
|
53
|
-
|
54
|
-
jgen.writeString(time);
|
50
|
+
serializeTime(dt, jgen, provider);
|
55
51
|
return;
|
56
52
|
}
|
57
53
|
|
58
54
|
method = meta.searchMethod("to_h");
|
59
55
|
if (!method.isUndefined()) {
|
60
56
|
RubyObject obj = (RubyObject) method.call(ctx, rubyObject, meta, "to_h");
|
61
|
-
|
57
|
+
serializeHash(obj, jgen, provider);
|
62
58
|
return;
|
63
59
|
}
|
64
60
|
|
65
61
|
method = meta.searchMethod("to_hash");
|
66
62
|
if (!method.isUndefined()) {
|
67
63
|
RubyObject obj = (RubyObject) method.call(ctx, rubyObject, meta, "to_hash");
|
68
|
-
|
64
|
+
serializeHash(obj, jgen, provider);
|
69
65
|
return;
|
70
66
|
}
|
71
67
|
|
72
68
|
method = meta.searchMethod("to_a");
|
73
69
|
if (!method.isUndefined()) {
|
74
70
|
RubyObject obj = (RubyObject) method.call(ctx, rubyObject, meta, "to_a");
|
75
|
-
|
71
|
+
serializeArray(obj, jgen, provider);
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
|
75
|
+
method = meta.searchMethod("to_json_data");
|
76
|
+
if (!method.isUndefined()) {
|
77
|
+
RubyObject obj = (RubyObject) method.call(ctx, rubyObject, meta, "to_json_data");
|
78
|
+
if (obj instanceof RubyString) {
|
79
|
+
RubyUtils.writeBytes(obj, jgen);
|
80
|
+
} else {
|
81
|
+
serialize(obj, jgen, provider);
|
82
|
+
}
|
76
83
|
return;
|
77
84
|
}
|
78
85
|
|
@@ -80,30 +87,36 @@ public class RubyAnySerializer extends StdSerializer<IRubyObject> {
|
|
80
87
|
if (!method.isUndefined()) {
|
81
88
|
RubyObject obj = (RubyObject) method.call(ctx, rubyObject, meta, "to_json");
|
82
89
|
if (obj instanceof RubyString) {
|
90
|
+
|
83
91
|
jgen.writeRawValue(obj.toString());
|
84
92
|
} else {
|
85
|
-
|
93
|
+
serialize(obj, jgen, provider);
|
86
94
|
}
|
87
95
|
return;
|
88
96
|
}
|
89
97
|
throw new JsonGenerationException("Cannot find Serializer for class: " + rubyObject.getClass().getName());
|
90
98
|
}
|
91
99
|
|
92
|
-
@Override
|
100
|
+
// @Override
|
93
101
|
public void serialize(IRubyObject value, JsonGenerator jgen, SerializerProvider provider)
|
94
102
|
throws IOException, JsonGenerationException {
|
95
|
-
|
103
|
+
|
96
104
|
if (value.isNil()) {
|
97
105
|
|
98
106
|
jgen.writeNull(); // for RubyNil and NullObjects
|
99
107
|
|
108
|
+
} else if (value instanceof JavaProxy) {
|
109
|
+
|
110
|
+
provider.defaultSerializeValue(((JavaProxy) value).getObject(), jgen);
|
111
|
+
|
100
112
|
} else if (value instanceof RubyString) {
|
101
113
|
|
102
|
-
|
114
|
+
RubyUtils.writeBytes(value, jgen);
|
103
115
|
|
104
116
|
} else if (value instanceof RubySymbol) {
|
105
|
-
|
106
|
-
|
117
|
+
// jgen.writeString(value.toString());
|
118
|
+
RubyString s = ((RubySymbol) value).asString();
|
119
|
+
jgen.writeUTF8String(s.getBytes(), 0, s.size());
|
107
120
|
|
108
121
|
} else if (value instanceof RubyBoolean) {
|
109
122
|
|
@@ -127,34 +140,79 @@ public class RubyAnySerializer extends StdSerializer<IRubyObject> {
|
|
127
140
|
|
128
141
|
} else if (value instanceof RubyHash) {
|
129
142
|
|
130
|
-
|
143
|
+
serializeHash(value, jgen, provider);
|
131
144
|
|
132
145
|
} else if (value instanceof RubyArray) {
|
133
146
|
|
134
|
-
|
147
|
+
serializeArray(value, jgen, provider);
|
135
148
|
|
136
149
|
} else if (value instanceof RubyStruct) {
|
137
150
|
|
138
|
-
IRubyObject obj = value.callMethod(
|
139
|
-
|
151
|
+
IRubyObject obj = value.callMethod(value.getRuntime().getCurrentContext(), "to_a");
|
152
|
+
serializeArray(obj, jgen, provider);
|
153
|
+
|
154
|
+
} else if (value instanceof RubyTime) {
|
155
|
+
// System.err.println("------->>>> RubyTime");
|
156
|
+
serializeTime((RubyTime) value, jgen, provider);
|
140
157
|
|
141
158
|
} else {
|
142
159
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
160
|
+
serializeUnknownRubyObject(value.getRuntime().getCurrentContext(), value, jgen, provider);
|
161
|
+
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
private void serializeArray(IRubyObject value, JsonGenerator jgen, SerializerProvider provider)
|
166
|
+
throws IOException, JsonGenerationException {
|
167
|
+
// System.err.println("----->> RubyArray");
|
168
|
+
|
169
|
+
RubyArray arr = (RubyArray) value;
|
170
|
+
IRubyObject[] a = arr.toJavaArray();
|
171
|
+
jgen.writeStartArray();
|
172
|
+
for (IRubyObject val : a) {
|
173
|
+
serialize(val, jgen, provider);
|
174
|
+
}
|
175
|
+
jgen.writeEndArray();
|
176
|
+
}
|
154
177
|
|
178
|
+
private void serializeHash(IRubyObject value, JsonGenerator jgen, SerializerProvider provider)
|
179
|
+
throws IOException, JsonGenerationException {
|
180
|
+
// System.err.println("----->> RubyHash");
|
181
|
+
|
182
|
+
RubyHash h = (RubyHash) value;
|
183
|
+
jgen.writeStartObject();
|
184
|
+
for (Object o : h.directEntrySet()) {
|
185
|
+
RubyHash.RubyHashEntry next = (RubyHash.RubyHashEntry) o;
|
186
|
+
serializeKey((IRubyObject) next.getKey(), jgen, provider);
|
187
|
+
serialize((IRubyObject) next.getValue(), jgen, provider);
|
188
|
+
}
|
189
|
+
jgen.writeEndObject();
|
190
|
+
}
|
191
|
+
|
192
|
+
private void serializeTime(RubyTime dt, JsonGenerator jgen, SerializerProvider provider)
|
193
|
+
throws IOException, JsonGenerationException {
|
194
|
+
DateFormat df = provider.getConfig().getDateFormat();
|
195
|
+
if (df == null) {
|
196
|
+
// DateFormat should always be set
|
197
|
+
provider.defaultSerializeDateValue(dt.getJavaDate(), jgen);
|
198
|
+
} else if (df instanceof RubyDateFormat) {
|
199
|
+
// why another branch? I thought there was an easy win on to_s
|
200
|
+
// maybe with jruby 9000
|
201
|
+
RubyDateFormat rdf = (RubyDateFormat) df.clone();
|
202
|
+
jgen.writeString(rdf.format(dt.getJavaDate()));
|
203
|
+
} else {
|
204
|
+
SimpleDateFormat sdf = (SimpleDateFormat) df.clone();
|
205
|
+
jgen.writeString(df.format(dt.getJavaDate()));
|
155
206
|
}
|
156
207
|
}
|
157
208
|
|
209
|
+
private void serializeKey(IRubyObject key, JsonGenerator jgen, SerializerProvider provider)
|
210
|
+
throws IOException, JsonGenerationException {
|
211
|
+
|
212
|
+
jgen.writeFieldName(key.asJavaString());
|
213
|
+
|
214
|
+
}
|
215
|
+
|
158
216
|
/**
|
159
217
|
* Default implementation will write type prefix, call regular serialization method (since assumption is that value itself does not need JSON Array or Object start/end markers), and then write type suffix. This should work for most cases; some sub-classes may want to change this behavior.
|
160
218
|
*
|
@@ -165,7 +223,6 @@ public class RubyAnySerializer extends StdSerializer<IRubyObject> {
|
|
165
223
|
* @throws java.io.IOException
|
166
224
|
* @throws com.fasterxml.jackson.core.JsonGenerationException
|
167
225
|
*/
|
168
|
-
@Override
|
169
226
|
public void serializeWithType(IRubyObject value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer)
|
170
227
|
throws IOException, JsonGenerationException {
|
171
228
|
typeSer.writeTypePrefixForScalar(value, jgen);
|
@@ -0,0 +1,18 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.JsonParser;
|
4
|
+
import java.io.IOException;
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyObject;
|
7
|
+
|
8
|
+
/**
|
9
|
+
*
|
10
|
+
* @author Guy Boertje
|
11
|
+
*/
|
12
|
+
public class RubyBigDecimalValueConverter implements RubyConverter {
|
13
|
+
|
14
|
+
@Override
|
15
|
+
public RubyObject convert(Ruby ruby, JsonParser jp) throws IOException {
|
16
|
+
return RubyUtils.rubyBigDecimal(ruby, jp.getDecimalValue());
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.JsonParser;
|
4
|
+
import java.io.IOException;
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyObject;
|
7
|
+
|
8
|
+
/**
|
9
|
+
*
|
10
|
+
* @author Guy Boertje
|
11
|
+
*/
|
12
|
+
public class RubyBigIntValueConverter implements RubyConverter {
|
13
|
+
|
14
|
+
@Override
|
15
|
+
public RubyObject convert(Ruby ruby, JsonParser jp) throws IOException {
|
16
|
+
if (jp.getNumberType() == JsonParser.NumberType.BIG_INTEGER) {
|
17
|
+
return RubyUtils.rubyBignum(ruby, jp.getBigIntegerValue());
|
18
|
+
}
|
19
|
+
return RubyUtils.rubyFixnum(ruby, jp.getLongValue());
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.*;
|
4
|
+
|
5
|
+
import java.io.IOException;
|
6
|
+
import org.jruby.Ruby;
|
7
|
+
import org.jruby.RubyObject;
|
8
|
+
|
9
|
+
public interface RubyConverter {
|
10
|
+
|
11
|
+
public RubyObject convert(Ruby ruby, JsonParser jp) throws IOException;
|
12
|
+
}
|