jrjackson 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d1c4ad52124b5b10d5b17ba157f5d7f51cd4f19
4
- data.tar.gz: 21381583fde4460338bf62312ddc5ae3d2bb484b
3
+ metadata.gz: ff0d3008ed2be467a14efa7ce22f17b798aff14f
4
+ data.tar.gz: 29acde65d94012d051d9ccd24dda9dfb4187cc6b
5
5
  SHA512:
6
- metadata.gz: 05c0daa5a1719b270c8f26269558fafb82002844be119a603970532f88246a104278c268975efcba9ac9afbddf61a235bb0e956ce6feb77695f8bdcee25781f1
7
- data.tar.gz: e2ffaa73398f0a08b4ca39ca50ee5e0dc9ffad2cd9ab9a1d052aa3b48e8cd2f1692e7225591968b7cf7699fc7a722953000f2ba670fa996598a0d4fcdc2e0494
6
+ metadata.gz: 49cad8b054b626adebd9d6a504b4b2d99df08a685f575d034e0ff957c772ee7f6c4bd2ceeec28b6ac41008f6877b54d95470d8de094a961a4dd3ec20bd3c63cd
7
+ data.tar.gz: a2f153ba800e763d4774473beeda5a3861b83303ec1fdd743a5751dc897a97df9796438044f08a45f880f464da67a15b8231d874d5fcbd25af49e30dc88fa026
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+
2
+
1
3
  LICENSE applicable to this library:
2
4
 
3
5
  Apache License 2.0 see http://www.apache.org/licenses/LICENSE-2.0
@@ -14,6 +16,15 @@ There is now a MultiJson adapter added for JrJackson
14
16
 
15
17
  ***
16
18
 
19
+ #### NEWS
20
+
21
+ 26th October 2013 - Added support to serialize arbitary (non JSON datatypes)
22
+ ruby objects. Normally the toJava internal metod is called, but additionally
23
+ to_h, to_hash, to_a and finally to_json are tried. Be aware that the to_json
24
+ method might invoke a new selialization session and impact performance.
25
+
26
+ ***
27
+
17
28
  #### API
18
29
 
19
30
  ```
@@ -76,8 +87,9 @@ generation/serialize
76
87
  json mri generate: 250 12.02 0.00 12.02 ( 12.022)
77
88
  oj mri generate: 250 7.18 0.00 7.18 ( 7.183)
78
89
  json java generate: 250 7.83 0.01 7.84 ( 7.289)
79
- gson generate: 250 5.44 0.00 5.44 ( 5.387)
80
- jackson generate: 250 5.32 0.00 5.32 ( 5.146)
90
+ gson generate: 250 5.04 0.00 5.04 ( 4.995)
91
+ jackson generate: 250 4.94 0.08 5.02 ( 4.811)
92
+
81
93
 
82
94
  parsing/deserialize - after jrjackson parsing profiling
83
95
 
@@ -92,9 +104,6 @@ jackson parse string + bigdecimal: 250 6.27 0.00 6.27 ( 5.973
92
104
  jackson parse symbol keys: 250 5.16 0.00 5.16 ( 4.873)
93
105
  jackson parse symbol + bigdecimal: 250 4.75 0.06 4.81 ( 4.461)
94
106
  jackson parse raw: 250 3.23 0.05 3.28 ( 3.021)
95
- jackson parse raw + bigdecimal: 250 3.06 0.06 3.12 ( 2.681)
107
+ jackson parse raw + bigdecimal: 250 3.06 0.06 3.12 ( 2.639)
96
108
 
97
109
  ```
98
-
99
-
100
-
@@ -4,7 +4,7 @@
4
4
  <groupId>com.jrjackson.jruby</groupId>
5
5
  <artifactId>jrjackson</artifactId>
6
6
  <name>jrjackson</name>
7
- <version>1.2.3</version>
7
+ <version>1.2.4</version>
8
8
  <url>http://maven.apache.org</url>
9
9
  <build>
10
10
  <plugins>
@@ -3,7 +3,8 @@ unless RUBY_PLATFORM =~ /java/
3
3
  exit 255
4
4
  end
5
5
 
6
- require_relative "jars/jrjackson-1.2.3.jar"
6
+ require_relative "jars/jrjackson-1.2.4.jar"
7
+ # require_relative "linked/jrjackson-1.2.4.jar"
7
8
 
8
9
  require 'com/jrjackson/jr_jackson'
9
10
 
@@ -1,3 +1,3 @@
1
1
  module JrJackson
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
data/pom.xml CHANGED
@@ -5,7 +5,7 @@
5
5
  <groupId>com.jrjackson.jruby</groupId>
6
6
  <artifactId>jrjackson</artifactId>
7
7
  <packaging>jar</packaging>
8
- <version>1.2.3</version>
8
+ <version>1.2.4</version>
9
9
  <name>jrjackson</name>
10
10
  <url>http://maven.apache.org</url>
11
11
 
@@ -144,9 +144,14 @@ public class JrJacksonRaw extends RubyObject {
144
144
 
145
145
  // serialize
146
146
  @JRubyMethod(module = true, name = {"generate", "dump"}, required = 1)
147
- public static IRubyObject generate(ThreadContext context, IRubyObject self, IRubyObject arg) {
147
+ public static IRubyObject generate(ThreadContext context, IRubyObject self, IRubyObject arg)
148
+ throws IOException, JsonProcessingException
149
+ {
148
150
  Ruby ruby = context.getRuntime();
149
151
  Object obj = arg.toJava(Object.class);
152
+ // String s = mappers.get("raw").writeValueAsString(obj);
153
+ // return RubyUtils.rubyString(ruby, s);
154
+
150
155
  try {
151
156
  String s = mappers.get("raw").writeValueAsString(obj);
152
157
  return RubyUtils.rubyString(ruby, s);
@@ -1,8 +1,9 @@
1
1
  package com.jrjackson;
2
2
 
3
3
  import org.jruby.Ruby;
4
- import org.jruby.RubyClass;
5
4
  import org.jruby.RubyModule;
5
+ import org.jruby.RubyClass;
6
+ import org.jruby.RubyObject;
6
7
  import org.jruby.runtime.ObjectAllocator;
7
8
  import org.jruby.runtime.builtin.IRubyObject;
8
9
  import org.jruby.runtime.load.BasicLibraryService;
@@ -0,0 +1,116 @@
1
+ package com.jrjackson;
2
+
3
+ import java.io.IOException;
4
+ import java.lang.reflect.Type;
5
+ import java.util.*;
6
+
7
+ import com.fasterxml.jackson.core.*;
8
+
9
+ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
10
+ import com.fasterxml.jackson.databind.JsonSerializer;
11
+ import com.fasterxml.jackson.databind.SerializerProvider;
12
+
13
+ import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
14
+
15
+ import org.jruby.*;
16
+ import org.jruby.runtime.ThreadContext;
17
+ import org.jruby.internal.runtime.methods.DynamicMethod;
18
+
19
+ public class RubyAnySerializer extends StdSerializer<RubyObject>
20
+ {
21
+ /**
22
+ * Singleton instance to use.
23
+ */
24
+ public static final RubyAnySerializer instance = new RubyAnySerializer();
25
+ private static HashMap<Class, Class> class_maps = new HashMap<Class, Class>();
26
+
27
+ static {
28
+ class_maps.put(RubyBoolean.class, Boolean.class);
29
+ }
30
+
31
+ public RubyAnySerializer() { super(RubyObject.class); }
32
+
33
+ private Class<?> rubyJavaClassLookup(Class target)
34
+ {
35
+ Class<?> val = class_maps.get(target);
36
+ if (val == null) {
37
+ return Object.class;
38
+ }
39
+ return val;
40
+ }
41
+
42
+ private void serializeUnknownRubyObject(RubyObject rubyObject, JsonGenerator jgen, SerializerProvider provider)
43
+ throws IOException, JsonGenerationException
44
+ {
45
+ ThreadContext ctx = rubyObject.getRuntime().getCurrentContext();
46
+ RubyClass meta = rubyObject.getMetaClass();
47
+ DynamicMethod method = meta.searchMethod("to_h");
48
+ if (!method.isUndefined()) {
49
+ RubyObject obj = (RubyObject)method.call(ctx, rubyObject, meta, "to_h");
50
+ provider.findTypedValueSerializer(Map.class, true, null).serialize(obj, jgen, provider);
51
+ return;
52
+ }
53
+
54
+ method = meta.searchMethod("to_hash");
55
+ if (!method.isUndefined()) {
56
+ RubyObject obj = (RubyObject)method.call(ctx, rubyObject, meta, "to_hash");
57
+ provider.findTypedValueSerializer(Map.class, true, null).serialize(obj, jgen, provider);
58
+ return;
59
+ }
60
+
61
+ method = meta.searchMethod("to_a");
62
+ if (!method.isUndefined()) {
63
+ RubyObject obj = (RubyObject)method.call(ctx, rubyObject, meta, "to_a");
64
+ provider.findTypedValueSerializer(List.class, true, null).serialize(obj, jgen, provider);
65
+ return;
66
+ }
67
+
68
+ method = meta.searchMethod("to_json");
69
+ if (!method.isUndefined()) {
70
+ RubyObject obj = (RubyObject)method.call(ctx, rubyObject, meta, "to_json");
71
+ if (obj instanceof RubyString) {
72
+ jgen.writeRawValue(obj.toString());
73
+ } else {
74
+ provider.defaultSerializeValue(obj, jgen);
75
+ }
76
+ return;
77
+ }
78
+ throw new JsonGenerationException("Cannot find Serializer for class: " + rubyObject.getClass().getName());
79
+ }
80
+
81
+ @Override
82
+ public void serialize(RubyObject value, JsonGenerator jgen, SerializerProvider provider)
83
+ throws IOException, JsonGenerationException
84
+ {
85
+ if (value instanceof RubySymbol || value instanceof RubyString) {
86
+ jgen.writeString(value.toString());
87
+ } else if (value instanceof RubyHash) {
88
+ provider.findTypedValueSerializer(Map.class, true, null).serialize(value, jgen, provider);
89
+ } else if (value instanceof RubyArray) {
90
+ provider.findTypedValueSerializer(List.class, true, null).serialize(value, jgen, provider);
91
+ } else {
92
+ Object val = value.toJava(rubyJavaClassLookup(value.getClass()));
93
+ if ( val instanceof RubyObject) {
94
+ serializeUnknownRubyObject((RubyObject)val, jgen, provider);
95
+ } else {
96
+ provider.defaultSerializeValue(val, jgen);
97
+ }
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Default implementation will write type prefix, call regular serialization
103
+ * method (since assumption is that value itself does not need JSON
104
+ * Array or Object start/end markers), and then write type suffix.
105
+ * This should work for most cases; some sub-classes may want to
106
+ * change this behavior.
107
+ */
108
+ @Override
109
+ public void serializeWithType(RubyObject value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer)
110
+ throws IOException, JsonGenerationException
111
+ {
112
+ typeSer.writeTypePrefixForScalar(value, jgen);
113
+ serialize(value, jgen, provider);
114
+ typeSer.writeTypeSuffixForScalar(value, jgen);
115
+ }
116
+ }
@@ -1,14 +1,16 @@
1
1
  package com.jrjackson;
2
2
 
3
3
  import java.util.*;
4
+ import java.text.SimpleDateFormat;
4
5
 
5
6
  import org.jruby.*;
6
- import org.jruby.util.RubyDateFormat;
7
+ // import org.jruby.util.RubyDateFormat;
7
8
 
8
9
  import com.fasterxml.jackson.databind.ObjectMapper;
9
10
  import com.fasterxml.jackson.databind.module.SimpleModule;
11
+ import com.fasterxml.jackson.databind.SerializationFeature;
10
12
  import com.fasterxml.jackson.core.util.VersionUtil;
11
- import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
13
+ import com.fasterxml.jackson.databind.ser.std.DateSerializer;
12
14
  import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
13
15
  import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
14
16
 
@@ -43,21 +45,22 @@ public class RubyJacksonModule extends SimpleModule
43
45
  asStr()
44
46
  );
45
47
  }
46
- mapper.setDateFormat(new RubyDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.US, true));
48
+ mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
49
+ mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"));
47
50
  return mapper;
48
51
  }
49
52
 
50
53
  public static SimpleModule asRaw()
51
54
  {
52
55
  return new RubyJacksonModule().addSerializer(
53
- RubySymbol.class, ToStringSerializer.instance
56
+ RubyObject.class, RubyAnySerializer.instance
54
57
  );
55
58
  }
56
59
 
57
60
  public static SimpleModule asSym()
58
61
  {
59
62
  return new RubyJacksonModule().addSerializer(
60
- RubySymbol.class, ToStringSerializer.instance
63
+ RubyObject.class, RubyAnySerializer.instance
61
64
  ).addDeserializer(
62
65
  Object.class, new RubyObjectDeserializer().setSymbolStrategy()
63
66
  );
@@ -66,7 +69,7 @@ public class RubyJacksonModule extends SimpleModule
66
69
  public static SimpleModule asStr()
67
70
  {
68
71
  return new RubyJacksonModule().addSerializer(
69
- RubySymbol.class, ToStringSerializer.instance
72
+ RubyObject.class, RubyAnySerializer.instance
70
73
  ).addDeserializer(
71
74
  Object.class, new RubyObjectDeserializer().setStringStrategy()
72
75
  );
@@ -26,8 +26,6 @@ public class RubyObjectDeserializer
26
26
 
27
27
  protected final static Ruby __ruby__ = Ruby.getGlobalRuntime();
28
28
 
29
- private static final HashMap<String, RubyKeyConverter> converters = new HashMap<String, RubyKeyConverter>(3);
30
-
31
29
  private RubyKeyConverter converter;
32
30
 
33
31
  public RubyObjectDeserializer() {
@@ -74,7 +72,8 @@ public class RubyObjectDeserializer
74
72
  return RubyUtils.rubyObject(__ruby__, jp.getEmbeddedObject());
75
73
 
76
74
  case VALUE_STRING:
77
- return RubyUtils.rubyString(__ruby__, jp.getText().getBytes());
75
+ // return RubyUtils.rubyString(__ruby__, jp.getText().getBytes("UTF-8"));
76
+ return RubyUtils.rubyString(__ruby__, jp.getText());
78
77
 
79
78
  case VALUE_NUMBER_INT:
80
79
  /* [JACKSON-100]: caller may want to get all integral values
@@ -90,7 +89,6 @@ public class RubyObjectDeserializer
90
89
  return RubyUtils.rubyBigDecimal(__ruby__, jp.getDecimalValue());
91
90
  }
92
91
  return RubyUtils.rubyFloat(__ruby__, jp.getDoubleValue());
93
- // return RubyUtils.rubyFloat(__ruby__, jp.getText());
94
92
 
95
93
  case VALUE_TRUE:
96
94
  return __ruby__.newBoolean(Boolean.TRUE);
@@ -1,5 +1,9 @@
1
+ # encoding: UTF-8
2
+
1
3
  $LOAD_PATH << File.expand_path('../../lib', __FILE__)
2
4
 
5
+ require "java"
6
+
3
7
  require 'test/unit'
4
8
  require 'thread'
5
9
  require 'bigdecimal'
@@ -7,6 +11,38 @@ require 'jrjackson'
7
11
 
8
12
  class JrJacksonTest < Test::Unit::TestCase
9
13
 
14
+ class CustomToH
15
+ attr_accessor :one, :two, :six
16
+ def initialize(a,b,c)
17
+ @one, @two, @six = a,b,c
18
+ end
19
+ def to_h
20
+ {'one' => one, 'two' => two, 'six' => six}
21
+ end
22
+ end
23
+
24
+ class CustomToHash
25
+ attr_accessor :one, :two, :six
26
+ def initialize(a,b,c)
27
+ @one, @two, @six = a,b,c
28
+ end
29
+ def to_hash
30
+ {'one' => one, 'two' => two, 'six' => six}
31
+ end
32
+ end
33
+
34
+ class CustomToJson
35
+ attr_accessor :one, :two, :six
36
+ def initialize(a,b,c)
37
+ @one, @two, @six = a,b,c
38
+ end
39
+ def to_json
40
+ %Q|{"one":#{one},"two":#{two},"six":#{six}}|
41
+ end
42
+ end
43
+
44
+ CustomStruct = Struct.new(:one, :two, :six)
45
+
10
46
  def test_threading
11
47
  q1, q2, q3 = Queue.new, Queue.new, Queue.new
12
48
 
@@ -28,10 +64,30 @@ class JrJacksonTest < Test::Unit::TestCase
28
64
  assert a3.values.all? {|v| v.is_a?(Float)}, "Expected all values to be Float"
29
65
  end
30
66
 
31
- def test_serialize_symbols_as_values
32
- source = {"first" => :first_symbol, "second" => {"inner" => :inner_symbol}}
33
- expected = {:first => "first_symbol", :second => {:inner => "inner_symbol"}}
34
- actual = JrJackson::Json.load(JrJackson::Json.dump(source), :symbolize_keys => true)
67
+ def test_deserialize_JSON_with_UTF8_characters
68
+ json_string = JrJackson::Json.dump({"utf8" => "żółć"})
69
+ expected = {utf8: "żółć"}
70
+ actual = JrJackson::Json.load(json_string, :symbolize_keys => true)
71
+ assert_equal expected, actual
72
+ end
73
+
74
+ def test_serialize_non_json_datatypes_as_values
75
+ dt = Time.now
76
+ co1 = CustomToH.new("uno", :two, 6.0)
77
+ co2 = CustomToHash.new("uno", :two, 6.0)
78
+ co3 = CustomToJson.new(1.0, 2, 6.0)
79
+ co4 = CustomStruct.new(1, 2, 6)
80
+ source = {"sym" => :a_symbol, "dt" => dt, "co1" => co1, "co2" => co2, "co3" => co3, "co4" => co4}
81
+ json_string = JrJackson::Json.dump(source)
82
+ expected = {
83
+ :sym => "a_symbol",
84
+ :dt => dt.strftime("%F %T %Z"),
85
+ :co1 => {:one => "uno", :two => "two", :six => 6.0 },
86
+ :co2 => {:one => "uno", :two => "two", :six => 6.0 },
87
+ :co3 => {:one => 1.0, :two => 2.0, :six => 6.0 },
88
+ :co4 => [1, 2, 6],
89
+ }
90
+ actual = JrJackson::Json.load(json_string, :symbolize_keys => true)
35
91
  assert_equal expected, actual
36
92
  end
37
93
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jrjackson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guy Boertje
@@ -59,7 +59,7 @@ files:
59
59
  - dependency-reduced-pom.xml
60
60
  - jrjackson.gemspec
61
61
  - lib/jrjackson.rb
62
- - lib/jrjackson/jars/jrjackson-1.2.3.jar
62
+ - lib/jrjackson/jars/jrjackson-1.2.4.jar
63
63
  - lib/jrjackson/jrjackson.rb
64
64
  - lib/jrjackson/version.rb
65
65
  - lib/require_relative_patch.rb
@@ -69,6 +69,7 @@ files:
69
69
  - src/main/java/com/jrjackson/JrJacksonRaw.java
70
70
  - src/main/java/com/jrjackson/JrJacksonService.java
71
71
  - src/main/java/com/jrjackson/ParseError.java
72
+ - src/main/java/com/jrjackson/RubyAnySerializer.java
72
73
  - src/main/java/com/jrjackson/RubyJacksonModule.java
73
74
  - src/main/java/com/jrjackson/RubyKeyConverter.java
74
75
  - src/main/java/com/jrjackson/RubyObjectDeserializer.java