jrjackson 0.2.9 → 0.3.0

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