jrjackson 0.2.9 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|