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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/{.jrubyrc → .__jrubyrc} +2 -2
  3. data/.gitignore +5 -0
  4. data/Gemfile +1 -0
  5. data/alt_bench.rb +46 -0
  6. data/dependency-reduced-pom.xml +6 -5
  7. data/lib/jrjackson/build_info.rb +2 -2
  8. data/lib/jrjackson/jars/jrjackson-1.2.16.jar +0 -0
  9. data/lib/jrjackson/jrjackson.rb +38 -13
  10. data/pom.xml +11 -10
  11. data/run_all_individual_bench.sh +17 -15
  12. data/run_jruby_individual_bench.sh +20 -0
  13. data/run_mri_individual_bench.sh +7 -0
  14. data/src/main/java/com/jrjackson/IParseHandler.java +53 -0
  15. data/src/main/java/com/jrjackson/JavaBigDecimalValueConverter.java +17 -0
  16. data/src/main/java/com/jrjackson/JavaBigIntValueConverter.java +17 -0
  17. data/src/main/java/com/jrjackson/JavaConverter.java +10 -0
  18. data/src/main/java/com/jrjackson/JavaFloatValueConverter.java +16 -0
  19. data/src/main/java/com/jrjackson/JavaHandler.java +118 -0
  20. data/src/main/java/com/jrjackson/JavaLongValueConverter.java +16 -0
  21. data/src/main/java/com/jrjackson/JjParse.java +147 -0
  22. data/src/main/java/com/jrjackson/JrJacksonBase.java +159 -0
  23. data/src/main/java/com/jrjackson/JrJacksonJava.java +81 -0
  24. data/src/main/java/com/jrjackson/JrJacksonRaw.java +59 -102
  25. data/src/main/java/com/jrjackson/JrJacksonRuby.java +117 -0
  26. data/src/main/java/com/jrjackson/JrJacksonSaj.java +26 -0
  27. data/src/main/java/com/jrjackson/JrJacksonSch.java +25 -0
  28. data/src/main/java/com/jrjackson/JrJacksonService.java +15 -0
  29. data/src/main/java/com/jrjackson/JrParse.java +149 -0
  30. data/src/main/java/com/jrjackson/RubyAnySerializer.java +112 -55
  31. data/src/main/java/com/jrjackson/RubyBigDecimalValueConverter.java +18 -0
  32. data/src/main/java/com/jrjackson/RubyBigIntValueConverter.java +21 -0
  33. data/src/main/java/com/jrjackson/RubyConverter.java +12 -0
  34. data/src/main/java/com/jrjackson/RubyDateFormat.java +36 -0
  35. data/src/main/java/com/jrjackson/RubyFloatValueConverter.java +18 -0
  36. data/src/main/java/com/jrjackson/RubyHandler.java +119 -0
  37. data/src/main/java/com/jrjackson/RubyIntValueConverter.java +18 -0
  38. data/src/main/java/com/jrjackson/RubyJacksonModule.java +40 -38
  39. data/src/main/java/com/jrjackson/RubyNameConverter.java +9 -0
  40. data/src/main/java/com/jrjackson/RubyObjectDeserializer.java +24 -33
  41. data/src/main/java/com/jrjackson/RubyStringConverter.java +1 -2
  42. data/src/main/java/com/jrjackson/{RubySymbolConverter.java → RubyStringKeyConverter.java} +3 -2
  43. data/src/main/java/com/jrjackson/RubyStringNameConverter.java +12 -0
  44. data/src/main/java/com/jrjackson/RubySymbolKeyConverter.java +15 -0
  45. data/src/main/java/com/jrjackson/RubySymbolNameConverter.java +12 -0
  46. data/src/main/java/com/jrjackson/RubyUtils.java +40 -1
  47. data/src/main/java/com/jrjackson/SajParse.java +169 -0
  48. data/src/main/java/com/jrjackson/SchParse.java +209 -0
  49. data/src/main/java/com/jrjackson/StreamParse.java +66 -0
  50. data/test/jrjackson_test.rb +271 -6
  51. metadata +49 -17
  52. 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 java.io.IOException;
4
- import java.util.*;
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
- import org.jruby.runtime.ThreadContext;
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
- public class RubyAnySerializer extends StdSerializer<IRubyObject> {
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
- String time = RubyUtils.jodaTimeString(dt.getDateTime());
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
- provider.findTypedValueSerializer(Map.class, true, null).serialize(obj, jgen, provider);
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
- provider.findTypedValueSerializer(Map.class, true, null).serialize(obj, jgen, provider);
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
- provider.findTypedValueSerializer(List.class, true, null).serialize(obj, jgen, provider);
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
- provider.defaultSerializeValue(obj, jgen);
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
- ThreadContext ctx = value.getRuntime().getCurrentContext();
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
- jgen.writeString(value.toString());
114
+ RubyUtils.writeBytes(value, jgen);
103
115
 
104
116
  } else if (value instanceof RubySymbol) {
105
-
106
- jgen.writeString(value.toString());
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
- provider.findTypedValueSerializer(value.getJavaClass(), true, null).serialize(value, jgen, provider);
143
+ serializeHash(value, jgen, provider);
131
144
 
132
145
  } else if (value instanceof RubyArray) {
133
146
 
134
- provider.findTypedValueSerializer(value.getJavaClass(), true, null).serialize(value, jgen, provider);
147
+ serializeArray(value, jgen, provider);
135
148
 
136
149
  } else if (value instanceof RubyStruct) {
137
150
 
138
- IRubyObject obj = value.callMethod(ctx, "to_a");
139
- provider.findTypedValueSerializer(obj.getJavaClass(), true, null).serialize(obj, jgen, provider);
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
- Class<?> cls = rubyJavaClassLookup(value.getClass());
144
- if (cls != null) {
145
- Object val = value.toJava(cls);
146
- if (val != null) {
147
- provider.defaultSerializeValue(val, jgen);
148
- } else {
149
- serializeUnknownRubyObject(ctx, value, jgen, provider);
150
- }
151
- } else {
152
- serializeUnknownRubyObject(ctx, value, jgen, provider);
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
+ }