jrjackson 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -6
- data/dependency-reduced-pom.xml +1 -1
- data/lib/jrjackson/jars/{jrjackson-1.2.3.jar → jrjackson-1.2.4.jar} +0 -0
- data/lib/jrjackson/jrjackson.rb +2 -1
- data/lib/jrjackson/version.rb +1 -1
- data/pom.xml +1 -1
- data/src/main/java/com/jrjackson/JrJacksonRaw.java +6 -1
- data/src/main/java/com/jrjackson/JrJacksonService.java +2 -1
- data/src/main/java/com/jrjackson/RubyAnySerializer.java +116 -0
- data/src/main/java/com/jrjackson/RubyJacksonModule.java +9 -6
- data/src/main/java/com/jrjackson/RubyObjectDeserializer.java +2 -4
- data/test/jrjackson_test.rb +60 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff0d3008ed2be467a14efa7ce22f17b798aff14f
|
4
|
+
data.tar.gz: 29acde65d94012d051d9ccd24dda9dfb4187cc6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
80
|
-
jackson generate: 250
|
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.
|
107
|
+
jackson parse raw + bigdecimal: 250 3.06 0.06 3.12 ( 2.639)
|
96
108
|
|
97
109
|
```
|
98
|
-
|
99
|
-
|
100
|
-
|
data/dependency-reduced-pom.xml
CHANGED
Binary file
|
data/lib/jrjackson/jrjackson.rb
CHANGED
data/lib/jrjackson/version.rb
CHANGED
data/pom.xml
CHANGED
@@ -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.
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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);
|
data/test/jrjackson_test.rb
CHANGED
@@ -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
|
32
|
-
|
33
|
-
expected = {:
|
34
|
-
actual = JrJackson::Json.load(
|
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.
|
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.
|
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
|