jrjackson 0.1.1 → 0.2.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.
- data/.jrubyrc +433 -0
- data/Gemfile +1 -1
- data/README.md +32 -23
- data/benchmarking/.jrubyrc +2 -2
- data/benchmarking/benchmark.rb +10 -58
- data/benchmarking/benchmark_threaded.rb +153 -0
- data/dependency-reduced-pom.xml +72 -0
- data/jrjackson.gemspec +11 -5
- data/lib/jrjackson/jars/jrjackson-1.2.2.jar +0 -0
- data/lib/jrjackson/jrjackson.rb +22 -18
- data/lib/jrjackson/version.rb +1 -2
- data/pom.xml +15 -10
- data/src/main/java/com/jrjackson/JrJacksonRaw.java +97 -12
- data/src/main/java/com/jrjackson/JrJacksonService.java +0 -6
- data/src/main/java/com/jrjackson/RubyJacksonModule.java +74 -0
- data/src/main/java/com/jrjackson/RubyObjectDeserializer.java +138 -222
- data/src/main/java/com/jrjackson/RubyObjectStrDeserializer.java +23 -0
- data/src/main/java/com/jrjackson/RubyObjectSymDeserializer.java +3 -60
- data/src/main/java/com/jrjackson/RubyUtils.java +77 -0
- data/src/test/java/com/jrjackson/jruby/AppTest.java +38 -0
- data/test/jrjackson_test.rb +63 -0
- metadata +17 -13
- data/lib/jrjackson/jars/jrjackson-1.0.jar +0 -0
- data/src/main/java/com/jrjackson/JrJacksonStr.java +0 -80
- data/src/main/java/com/jrjackson/JrJacksonSym.java +0 -80
data/lib/jrjackson/version.rb
CHANGED
data/pom.xml
CHANGED
@@ -5,10 +5,10 @@
|
|
5
5
|
<groupId>com.jrjackson.jruby</groupId>
|
6
6
|
<artifactId>jrjackson</artifactId>
|
7
7
|
<packaging>jar</packaging>
|
8
|
-
<version>1.
|
8
|
+
<version>1.2.2</version>
|
9
9
|
<name>jrjackson</name>
|
10
10
|
<url>http://maven.apache.org</url>
|
11
|
-
|
11
|
+
|
12
12
|
<properties>
|
13
13
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
14
14
|
</properties>
|
@@ -28,17 +28,22 @@
|
|
28
28
|
<dependency>
|
29
29
|
<groupId>com.fasterxml.jackson.core</groupId>
|
30
30
|
<artifactId>jackson-core</artifactId>
|
31
|
-
<version>2.
|
31
|
+
<version>2.2.2</version>
|
32
32
|
</dependency>
|
33
33
|
<dependency>
|
34
34
|
<groupId>com.fasterxml.jackson.core</groupId>
|
35
35
|
<artifactId>jackson-annotations</artifactId>
|
36
|
-
<version>2.
|
36
|
+
<version>2.2.2</version>
|
37
37
|
</dependency>
|
38
38
|
<dependency>
|
39
39
|
<groupId>com.fasterxml.jackson.core</groupId>
|
40
40
|
<artifactId>jackson-databind</artifactId>
|
41
|
-
<version>2.
|
41
|
+
<version>2.2.2</version>
|
42
|
+
</dependency>
|
43
|
+
<dependency>
|
44
|
+
<groupId>com.fasterxml.jackson.module</groupId>
|
45
|
+
<artifactId>jackson-module-afterburner</artifactId>
|
46
|
+
<version>2.2.2</version>
|
42
47
|
</dependency>
|
43
48
|
</dependencies>
|
44
49
|
<build>
|
@@ -46,16 +51,16 @@
|
|
46
51
|
<plugin>
|
47
52
|
<groupId>org.apache.maven.plugins</groupId>
|
48
53
|
<artifactId>maven-compiler-plugin</artifactId>
|
49
|
-
<version>3.
|
54
|
+
<version>3.1</version>
|
50
55
|
<configuration>
|
51
|
-
<source>1.
|
52
|
-
<target>1.
|
56
|
+
<source>1.7</source>
|
57
|
+
<target>1.7</target>
|
53
58
|
</configuration>
|
54
59
|
</plugin>
|
55
60
|
<plugin>
|
56
61
|
<groupId>org.apache.maven.plugins</groupId>
|
57
62
|
<artifactId>maven-surefire-plugin</artifactId>
|
58
|
-
<version>2.
|
63
|
+
<version>2.16</version>
|
59
64
|
<configuration>
|
60
65
|
<parallel>methods</parallel>
|
61
66
|
<threadCount>10</threadCount>
|
@@ -64,7 +69,7 @@
|
|
64
69
|
<plugin>
|
65
70
|
<groupId>org.apache.maven.plugins</groupId>
|
66
71
|
<artifactId>maven-shade-plugin</artifactId>
|
67
|
-
<version>1
|
72
|
+
<version>2.1</version>
|
68
73
|
<executions>
|
69
74
|
<execution>
|
70
75
|
<phase>package</phase>
|
@@ -4,51 +4,135 @@ import org.jruby.Ruby;
|
|
4
4
|
import org.jruby.RubyClass;
|
5
5
|
import org.jruby.RubyObject;
|
6
6
|
import org.jruby.RubyString;
|
7
|
+
import org.jruby.RubySymbol;
|
8
|
+
import org.jruby.RubyHash;
|
7
9
|
import org.jruby.RubyIO;
|
8
10
|
import org.jruby.anno.JRubyMethod;
|
9
11
|
import org.jruby.anno.JRubyModule;
|
10
12
|
import org.jruby.exceptions.RaiseException;
|
11
13
|
import org.jruby.ext.stringio.RubyStringIO;
|
12
14
|
import org.jruby.java.addons.IOJavaAddons;
|
13
|
-
import org.jruby.javasupport.JavaUtil;
|
14
15
|
import org.jruby.runtime.ThreadContext;
|
15
16
|
import org.jruby.runtime.builtin.IRubyObject;
|
16
|
-
import org.jruby.util.RubyDateFormat;
|
17
17
|
|
18
18
|
import java.io.InputStream;
|
19
19
|
import java.io.IOException;
|
20
|
-
import java.text.DateFormat;
|
21
20
|
import java.util.*;
|
22
21
|
|
23
22
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
23
|
+
import com.fasterxml.jackson.databind.DeserializationFeature;
|
24
24
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
25
25
|
|
26
26
|
@JRubyModule(name = "JrJacksonRaw")
|
27
27
|
public class JrJacksonRaw extends RubyObject {
|
28
|
-
|
28
|
+
private static final HashMap<String, ObjectMapper> mappers = new HashMap<String, ObjectMapper>(3);
|
29
|
+
private static final HashMap<String, RubySymbol> symbols = new HashMap<String, RubySymbol>(3);
|
30
|
+
|
31
|
+
private static final Ruby _ruby = Ruby.getGlobalRuntime();
|
29
32
|
|
30
33
|
static {
|
31
|
-
|
34
|
+
mappers.put("str",
|
35
|
+
RubyJacksonModule.mappedAs("str")
|
36
|
+
);
|
37
|
+
mappers.put("sym",
|
38
|
+
RubyJacksonModule.mappedAs("sym")
|
39
|
+
);
|
40
|
+
mappers.put("raw",
|
41
|
+
RubyJacksonModule.mappedAs("raw")
|
42
|
+
);
|
43
|
+
symbols.put("sym",
|
44
|
+
RubyUtils.rubySymbol(_ruby, "symbolize_keys")
|
45
|
+
);
|
46
|
+
symbols.put("raw",
|
47
|
+
RubyUtils.rubySymbol(_ruby, "raw")
|
48
|
+
);
|
49
|
+
symbols.put("bigdecimal",
|
50
|
+
RubyUtils.rubySymbol(_ruby, "use_bigdecimal")
|
51
|
+
);
|
32
52
|
}
|
33
53
|
|
34
54
|
public JrJacksonRaw(Ruby ruby, RubyClass metaclass) {
|
35
55
|
super(ruby, metaclass);
|
36
56
|
}
|
37
57
|
|
38
|
-
|
39
|
-
|
58
|
+
private static boolean flagged(RubyHash opts, String key) {
|
59
|
+
Object val = opts.get(symbols.get(key));
|
60
|
+
if (val == null) {
|
61
|
+
return false;
|
62
|
+
}
|
63
|
+
return (Boolean) val;
|
64
|
+
}
|
65
|
+
|
66
|
+
// deserialize
|
67
|
+
@JRubyMethod(module = true, name = {"parse", "load"}, required = 2)
|
68
|
+
public static IRubyObject parse(ThreadContext context, IRubyObject self, IRubyObject arg, IRubyObject opts)
|
69
|
+
throws IOException
|
70
|
+
{
|
71
|
+
RubyHash options = null;
|
72
|
+
String key = "str";
|
73
|
+
ObjectMapper local;
|
74
|
+
|
75
|
+
if (opts != context.nil) {
|
76
|
+
options = opts.convertToHash();
|
77
|
+
if (flagged(options, "sym")) {
|
78
|
+
key = "sym";
|
79
|
+
}
|
80
|
+
if (flagged(options, "raw")) {
|
81
|
+
key = "raw";
|
82
|
+
}
|
83
|
+
local = mappers.get(key).copy();
|
84
|
+
if (flagged(options, "bigdecimal")) {
|
85
|
+
local.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
local.disable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
else {
|
92
|
+
local = mappers.get(key).copy();
|
93
|
+
}
|
94
|
+
return _parse(context, arg, local);
|
95
|
+
}
|
96
|
+
|
97
|
+
@JRubyMethod(module = true, name = {"parse_raw", "load_raw"}, required = 1)
|
98
|
+
public static IRubyObject parse_raw(ThreadContext context, IRubyObject self, IRubyObject arg)
|
99
|
+
throws IOException
|
100
|
+
{
|
101
|
+
return _parse(context, arg, mappers.get("raw"));
|
102
|
+
}
|
103
|
+
|
104
|
+
@JRubyMethod(module = true, name = {"parse_sym", "load_sym"}, required = 1)
|
105
|
+
public static IRubyObject parse_sym(ThreadContext context, IRubyObject self, IRubyObject arg)
|
106
|
+
throws IOException
|
107
|
+
{
|
108
|
+
return _parse(context, arg, mappers.get("sym"));
|
109
|
+
}
|
110
|
+
|
111
|
+
@JRubyMethod(module = true, name = {"parse_str", "load_str"}, required = 1)
|
112
|
+
public static IRubyObject parse_str(ThreadContext context, IRubyObject self, IRubyObject arg)
|
113
|
+
throws IOException
|
114
|
+
{
|
115
|
+
return _parse(context, arg, mappers.get("str"));
|
116
|
+
}
|
117
|
+
|
118
|
+
public static IRubyObject _parse(ThreadContext context, IRubyObject arg, ObjectMapper mapper)
|
119
|
+
throws IOException
|
120
|
+
{
|
40
121
|
Ruby ruby = context.getRuntime();
|
122
|
+
|
41
123
|
try {
|
42
124
|
Object o;
|
43
125
|
if (arg instanceof RubyString) {
|
44
|
-
o = mapper.readValue(
|
126
|
+
o = mapper.readValue(
|
127
|
+
arg.toString(), Object.class
|
128
|
+
);
|
45
129
|
} else if ((arg instanceof RubyIO) || (arg instanceof RubyStringIO)) {
|
46
130
|
IRubyObject stream = IOJavaAddons.AnyIO.any_to_inputstream(context, arg);
|
47
|
-
o =
|
131
|
+
o = mapper.readValue((InputStream)stream.toJava(InputStream.class), Object.class);
|
48
132
|
} else {
|
49
133
|
throw ruby.newArgumentError("Unsupported source. This method accepts String or IO");
|
50
134
|
}
|
51
|
-
return
|
135
|
+
return RubyUtils.rubyObject(ruby, o);
|
52
136
|
}
|
53
137
|
catch (JsonProcessingException e) {
|
54
138
|
throw ParseError.newParseError(ruby, e.getLocalizedMessage());
|
@@ -58,13 +142,14 @@ public class JrJacksonRaw extends RubyObject {
|
|
58
142
|
}
|
59
143
|
}
|
60
144
|
|
145
|
+
// serialize
|
61
146
|
@JRubyMethod(module = true, name = {"generate", "dump"}, required = 1)
|
62
147
|
public static IRubyObject generate(ThreadContext context, IRubyObject self, IRubyObject arg) {
|
63
148
|
Ruby ruby = context.getRuntime();
|
64
149
|
Object obj = arg.toJava(Object.class);
|
65
150
|
try {
|
66
|
-
String s =
|
67
|
-
return
|
151
|
+
String s = mappers.get("raw").writeValueAsString(obj);
|
152
|
+
return RubyUtils.rubyString(ruby, s);
|
68
153
|
}
|
69
154
|
catch (JsonProcessingException e) {
|
70
155
|
throw ParseError.newParseError(ruby, e.getLocalizedMessage());
|
@@ -13,15 +13,9 @@ 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_str = ruby.defineModuleUnder("Str", jr_jackson);
|
17
|
-
jr_jackson_str.defineAnnotatedMethods(JrJacksonStr.class);
|
18
|
-
|
19
16
|
RubyModule jr_jackson_raw = ruby.defineModuleUnder("Raw", jr_jackson);
|
20
17
|
jr_jackson_raw.defineAnnotatedMethods(JrJacksonRaw.class);
|
21
18
|
|
22
|
-
RubyModule jr_jackson_sym = ruby.defineModuleUnder("Sym", jr_jackson);
|
23
|
-
jr_jackson_sym.defineAnnotatedMethods(JrJacksonSym.class);
|
24
|
-
|
25
19
|
RubyClass runtimeError = ruby.getRuntimeError();
|
26
20
|
RubyClass parseError = jr_jackson.defineClassUnder("ParseError", runtimeError, runtimeError.getAllocator());
|
27
21
|
return true;
|
@@ -0,0 +1,74 @@
|
|
1
|
+
package com.jrjackson;
|
2
|
+
|
3
|
+
import java.util.*;
|
4
|
+
|
5
|
+
import org.jruby.*;
|
6
|
+
import org.jruby.util.RubyDateFormat;
|
7
|
+
|
8
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
9
|
+
import com.fasterxml.jackson.databind.module.SimpleModule;
|
10
|
+
import com.fasterxml.jackson.core.util.VersionUtil;
|
11
|
+
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
12
|
+
|
13
|
+
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
|
14
|
+
|
15
|
+
public class RubyJacksonModule extends SimpleModule
|
16
|
+
{
|
17
|
+
|
18
|
+
private RubyJacksonModule()
|
19
|
+
{
|
20
|
+
super("JrJacksonStrModule", VersionUtil.versionFor(RubyJacksonModule.class));
|
21
|
+
}
|
22
|
+
|
23
|
+
public static ObjectMapper mappedAs(String key)
|
24
|
+
{
|
25
|
+
ObjectMapper mapper = new ObjectMapper();
|
26
|
+
|
27
|
+
mapper.registerModule(
|
28
|
+
new AfterburnerModule()
|
29
|
+
);
|
30
|
+
|
31
|
+
if (key == "sym") {
|
32
|
+
mapper.registerModule(
|
33
|
+
asSym()
|
34
|
+
);
|
35
|
+
}
|
36
|
+
else if (key == "raw") {
|
37
|
+
mapper.registerModule(
|
38
|
+
asRaw()
|
39
|
+
);
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
mapper.registerModule(
|
43
|
+
asStr()
|
44
|
+
);
|
45
|
+
}
|
46
|
+
mapper.setDateFormat(new RubyDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.US, true));
|
47
|
+
return mapper;
|
48
|
+
}
|
49
|
+
|
50
|
+
public static SimpleModule asRaw()
|
51
|
+
{
|
52
|
+
return new RubyJacksonModule().addSerializer(
|
53
|
+
RubySymbol.class, ToStringSerializer.instance
|
54
|
+
);
|
55
|
+
}
|
56
|
+
|
57
|
+
public static SimpleModule asSym()
|
58
|
+
{
|
59
|
+
return new RubyJacksonModule().addSerializer(
|
60
|
+
RubySymbol.class, ToStringSerializer.instance
|
61
|
+
).addDeserializer(
|
62
|
+
Object.class, RubyObjectSymDeserializer.instance
|
63
|
+
);
|
64
|
+
}
|
65
|
+
|
66
|
+
public static SimpleModule asStr()
|
67
|
+
{
|
68
|
+
return new RubyJacksonModule().addSerializer(
|
69
|
+
RubySymbol.class, ToStringSerializer.instance
|
70
|
+
).addDeserializer(
|
71
|
+
Object.class, RubyObjectStrDeserializer.instance
|
72
|
+
);
|
73
|
+
}
|
74
|
+
}
|
@@ -7,8 +7,6 @@ import com.fasterxml.jackson.core.*;
|
|
7
7
|
|
8
8
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
9
9
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
10
|
-
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
|
11
|
-
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
|
12
10
|
import com.fasterxml.jackson.databind.util.ObjectBuffer;
|
13
11
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
14
12
|
|
@@ -16,242 +14,160 @@ import org.jruby.Ruby;
|
|
16
14
|
import org.jruby.RubyObject;
|
17
15
|
import org.jruby.RubyArray;
|
18
16
|
import org.jruby.RubyHash;
|
19
|
-
import org.jruby.RubyString;
|
20
|
-
import org.jruby.runtime.builtin.IRubyObject;
|
21
|
-
import org.jruby.javasupport.JavaUtil;
|
22
17
|
import org.jruby.javasupport.util.RuntimeHelpers;
|
23
18
|
|
24
19
|
|
25
|
-
public class RubyObjectDeserializer
|
26
|
-
|
20
|
+
public abstract class RubyObjectDeserializer
|
21
|
+
extends StdDeserializer<RubyObject>
|
27
22
|
{
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
case VALUE_NUMBER_FLOAT:
|
73
|
-
/* [JACKSON-72]: need to allow overriding the behavior regarding
|
74
|
-
* which type to use
|
75
|
-
*/
|
76
|
-
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
|
77
|
-
return toRuby(jp.getDecimalValue());
|
78
|
-
}
|
79
|
-
return toRuby(Double.valueOf(jp.getDoubleValue()));
|
80
|
-
|
81
|
-
case VALUE_TRUE:
|
82
|
-
return __ruby__.newBoolean(Boolean.TRUE);
|
83
|
-
case VALUE_FALSE:
|
84
|
-
return __ruby__.newBoolean(Boolean.FALSE);
|
85
|
-
|
86
|
-
case VALUE_NULL: // should not get this but...
|
87
|
-
return null;
|
88
|
-
|
89
|
-
case END_ARRAY: // invalid
|
90
|
-
case END_OBJECT: // invalid
|
91
|
-
default:
|
92
|
-
throw ctxt.mappingException(Object.class);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
|
96
|
-
@Override
|
97
|
-
public RubyObject deserializeWithType(JsonParser jp, DeserializationContext ctxt,
|
98
|
-
TypeDeserializer typeDeserializer)
|
99
|
-
throws IOException, JsonProcessingException
|
100
|
-
{
|
101
|
-
JsonToken t = jp.getCurrentToken();
|
102
|
-
switch (t) {
|
103
|
-
// First: does it look like we had type id wrapping of some kind?
|
104
|
-
case START_ARRAY:
|
105
|
-
case START_OBJECT:
|
106
|
-
case FIELD_NAME:
|
107
|
-
/* Output can be as JSON Object, Array or scalar: no way to know
|
108
|
-
* a this point:
|
109
|
-
*/
|
110
|
-
return toRuby(typeDeserializer.deserializeTypedFromAny(jp, ctxt));
|
111
|
-
|
112
|
-
/* Otherwise we probably got a "native" type (ones that map
|
113
|
-
* naturally and thus do not need or use type ids)
|
23
|
+
private static final long serialVersionUID = 1L;
|
24
|
+
|
25
|
+
private final static RubyObject[] NO_OBJECTS = new RubyObject[0];
|
26
|
+
|
27
|
+
protected final static Ruby __ruby__ = Ruby.getGlobalRuntime();
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @since 2.2
|
31
|
+
*/
|
32
|
+
|
33
|
+
public RubyObjectDeserializer() { super(RubyObject.class); }
|
34
|
+
|
35
|
+
protected abstract RubyObject convertKey(JsonParser jp)
|
36
|
+
throws IOException;
|
37
|
+
|
38
|
+
/**
|
39
|
+
/**********************************************************
|
40
|
+
/* Deserializer API
|
41
|
+
/**********************************************************
|
42
|
+
*/
|
43
|
+
|
44
|
+
@Override
|
45
|
+
public RubyObject deserialize(JsonParser jp, DeserializationContext ctxt)
|
46
|
+
throws IOException, JsonProcessingException
|
47
|
+
{
|
48
|
+
switch (jp.getCurrentToken()) {
|
49
|
+
case START_OBJECT:
|
50
|
+
return mapObject(jp, ctxt);
|
51
|
+
|
52
|
+
case START_ARRAY:
|
53
|
+
return mapArray(jp, ctxt);
|
54
|
+
|
55
|
+
case FIELD_NAME:
|
56
|
+
return convertKey(jp);
|
57
|
+
|
58
|
+
case VALUE_EMBEDDED_OBJECT:
|
59
|
+
return RubyUtils.rubyObject(__ruby__, jp.getEmbeddedObject());
|
60
|
+
|
61
|
+
case VALUE_STRING:
|
62
|
+
return RubyUtils.rubyString(__ruby__, jp.getText());
|
63
|
+
|
64
|
+
case VALUE_NUMBER_INT:
|
65
|
+
/* [JACKSON-100]: caller may want to get all integral values
|
66
|
+
* returned as BigInteger, for consistency
|
114
67
|
*/
|
115
|
-
|
116
|
-
return
|
68
|
+
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
|
69
|
+
return RubyUtils.rubyBignum(__ruby__, jp.getBigIntegerValue());
|
70
|
+
}
|
71
|
+
return RubyUtils.rubyFixnum(__ruby__, jp.getLongValue());
|
72
|
+
|
73
|
+
case VALUE_NUMBER_FLOAT:
|
74
|
+
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
|
75
|
+
return RubyUtils.rubyBigDecimal(__ruby__, jp.getDecimalValue());
|
76
|
+
}
|
77
|
+
return RubyUtils.rubyFloat(__ruby__, jp.getDoubleValue());
|
117
78
|
|
118
|
-
|
119
|
-
|
120
|
-
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
|
121
|
-
return toRuby(jp.getBigIntegerValue());
|
122
|
-
}
|
123
|
-
/* and as per [JACKSON-839], allow "upgrade" to bigger types: out-of-range
|
124
|
-
* entries can not be produced without type, so this should "just work",
|
125
|
-
* even if it is bit unclean
|
126
|
-
*/
|
127
|
-
return toRuby(jp.getNumberValue());
|
79
|
+
case VALUE_TRUE:
|
80
|
+
return __ruby__.newBoolean(Boolean.TRUE);
|
128
81
|
|
129
|
-
|
130
|
-
|
131
|
-
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
|
132
|
-
return toRuby(jp.getDecimalValue());
|
133
|
-
}
|
134
|
-
return __ruby__.newFloat(Double.valueOf(jp.getDoubleValue()));
|
82
|
+
case VALUE_FALSE:
|
83
|
+
return __ruby__.newBoolean(Boolean.FALSE);
|
135
84
|
|
136
|
-
|
137
|
-
|
138
|
-
case VALUE_FALSE:
|
139
|
-
return __ruby__.newBoolean(Boolean.FALSE);
|
140
|
-
case VALUE_EMBEDDED_OBJECT:
|
141
|
-
return toRuby(jp.getEmbeddedObject());
|
85
|
+
case VALUE_NULL: // should not get this but...
|
86
|
+
return null;
|
142
87
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
}
|
88
|
+
case END_ARRAY: // invalid
|
89
|
+
case END_OBJECT: // invalid
|
90
|
+
default:
|
91
|
+
throw ctxt.mappingException(Object.class);
|
148
92
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
/**********************************************************
|
97
|
+
/* Internal methods
|
98
|
+
/**********************************************************
|
99
|
+
*/
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Method called to map a JSON Array into a Java value.
|
103
|
+
*/
|
104
|
+
protected RubyObject mapArray(JsonParser jp, DeserializationContext ctxt)
|
105
|
+
throws IOException, JsonProcessingException
|
106
|
+
{
|
107
|
+
// if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
|
108
|
+
// return mapArrayToArray(jp, ctxt);
|
109
|
+
// }
|
110
|
+
// Minor optimization to handle small lists (default size for ArrayList is 10)
|
111
|
+
if (jp.nextToken() == JsonToken.END_ARRAY) {
|
112
|
+
return RubyArray.newArray(__ruby__);
|
158
113
|
}
|
159
|
-
|
160
|
-
|
161
|
-
|
114
|
+
ObjectBuffer buffer = ctxt.leaseObjectBuffer();
|
115
|
+
Object[] values = buffer.resetAndStart();
|
116
|
+
int ptr = 0;
|
117
|
+
long totalSize = 0;
|
118
|
+
do {
|
119
|
+
Object value = deserialize(jp, ctxt);
|
120
|
+
++totalSize;
|
121
|
+
if (ptr >= values.length) {
|
122
|
+
values = buffer.appendCompletedChunk(values);
|
123
|
+
ptr = 0;
|
124
|
+
}
|
125
|
+
values[ptr++] = value;
|
126
|
+
} while (jp.nextToken() != JsonToken.END_ARRAY);
|
127
|
+
// let's create almost full array, with 1/8 slack
|
128
|
+
RubyArray result = RubyArray.newArray(__ruby__, (totalSize + (totalSize >> 3) + 1));
|
129
|
+
buffer.completeAndClearBuffer(values, ptr, result);
|
130
|
+
return result;
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Method called to map a JSON Object into a Java value.
|
135
|
+
*/
|
136
|
+
protected RubyObject mapObject(JsonParser jp, DeserializationContext ctxt)
|
137
|
+
throws IOException, JsonProcessingException
|
138
|
+
{
|
139
|
+
JsonToken t = jp.getCurrentToken();
|
140
|
+
if (t == JsonToken.START_OBJECT) {
|
141
|
+
t = jp.nextToken();
|
142
|
+
}
|
143
|
+
// 1.6: minor optimization; let's handle 1 and 2 entry cases separately
|
144
|
+
if (t != JsonToken.FIELD_NAME) { // and empty one too
|
145
|
+
// empty map might work; but caller may want to modify... so better just give small modifiable
|
146
|
+
return RubyHash.newHash(__ruby__);
|
162
147
|
}
|
163
148
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
{
|
170
|
-
// if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
|
171
|
-
// return mapArrayToArray(jp, ctxt);
|
172
|
-
// }
|
173
|
-
// Minor optimization to handle small lists (default size for ArrayList is 10)
|
174
|
-
if (jp.nextToken() == JsonToken.END_ARRAY) {
|
175
|
-
return RubyArray.newArray(__ruby__);
|
176
|
-
}
|
177
|
-
ObjectBuffer buffer = ctxt.leaseObjectBuffer();
|
178
|
-
Object[] values = buffer.resetAndStart();
|
179
|
-
int ptr = 0;
|
180
|
-
long totalSize = 0;
|
181
|
-
do {
|
182
|
-
Object value = deserialize(jp, ctxt);
|
183
|
-
++totalSize;
|
184
|
-
if (ptr >= values.length) {
|
185
|
-
values = buffer.appendCompletedChunk(values);
|
186
|
-
ptr = 0;
|
187
|
-
}
|
188
|
-
values[ptr++] = value;
|
189
|
-
} while (jp.nextToken() != JsonToken.END_ARRAY);
|
190
|
-
// let's create almost full array, with 1/8 slack
|
191
|
-
RubyArray result = RubyArray.newArray(__ruby__, (totalSize + (totalSize >> 3) + 1));
|
192
|
-
buffer.completeAndClearBuffer(values, ptr, result);
|
193
|
-
return result;
|
149
|
+
RubyObject field1 = convertKey(jp);
|
150
|
+
jp.nextToken();
|
151
|
+
RubyObject value1 = deserialize(jp, ctxt);
|
152
|
+
if (jp.nextToken() != JsonToken.FIELD_NAME) { // single entry; but we want modifiable
|
153
|
+
return RuntimeHelpers.constructHash(__ruby__, field1, value1);
|
194
154
|
}
|
195
155
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
{
|
202
|
-
JsonToken t = jp.getCurrentToken();
|
203
|
-
if (t == JsonToken.START_OBJECT) {
|
204
|
-
t = jp.nextToken();
|
205
|
-
}
|
206
|
-
// 1.6: minor optimization; let's handle 1 and 2 entry cases separately
|
207
|
-
if (t != JsonToken.FIELD_NAME) { // and empty one too
|
208
|
-
// empty map might work; but caller may want to modify... so better just give small modifiable
|
209
|
-
return RubyHash.newHash(__ruby__);
|
210
|
-
}
|
211
|
-
RubyString field1 = rubyString(jp);
|
212
|
-
jp.nextToken();
|
213
|
-
RubyObject value1 = deserialize(jp, ctxt);
|
214
|
-
if (jp.nextToken() != JsonToken.FIELD_NAME) { // single entry; but we want modifiable
|
215
|
-
return RuntimeHelpers.constructHash(__ruby__, field1, value1);
|
216
|
-
}
|
217
|
-
RubyString field2 = rubyString(jp);
|
218
|
-
jp.nextToken();
|
219
|
-
RubyObject value2 = deserialize(jp, ctxt);
|
220
|
-
if (jp.nextToken() != JsonToken.FIELD_NAME) {
|
221
|
-
return RuntimeHelpers.constructHash(__ruby__, field1, value1, field2, value2);
|
222
|
-
}
|
223
|
-
// And then the general case; default map size is 16
|
224
|
-
RubyHash result = RuntimeHelpers.constructHash(__ruby__, field1, value1, field2, value2);
|
225
|
-
do {
|
226
|
-
RubyString fieldName = rubyString(jp);
|
227
|
-
jp.nextToken();
|
228
|
-
result.fastASet(fieldName, deserialize(jp, ctxt));
|
229
|
-
} while (jp.nextToken() != JsonToken.END_OBJECT);
|
230
|
-
return result;
|
156
|
+
RubyObject field2 = convertKey(jp);
|
157
|
+
jp.nextToken();
|
158
|
+
RubyObject value2 = deserialize(jp, ctxt);
|
159
|
+
if (jp.nextToken() != JsonToken.FIELD_NAME) {
|
160
|
+
return RuntimeHelpers.constructHash(__ruby__, field1, value1, field2, value2);
|
231
161
|
}
|
232
162
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
// }
|
243
|
-
// ObjectBuffer buffer = ctxt.leaseObjectBuffer();
|
244
|
-
// Object[] values = buffer.resetAndStart();
|
245
|
-
// int ptr = 0;
|
246
|
-
// do {
|
247
|
-
// Object value = deserialize(jp, ctxt);
|
248
|
-
// if (ptr >= values.length) {
|
249
|
-
// values = buffer.appendCompletedChunk(values);
|
250
|
-
// ptr = 0;
|
251
|
-
// }
|
252
|
-
// values[ptr++] = value;
|
253
|
-
// } while (jp.nextToken() != JsonToken.END_ARRAY);
|
254
|
-
// return buffer.completeAndClearBuffer(values, ptr);
|
255
|
-
// }
|
163
|
+
// And then the general case; default map size is 16
|
164
|
+
RubyHash result = RuntimeHelpers.constructHash(__ruby__, field1, value1, field2, value2);
|
165
|
+
do {
|
166
|
+
RubyObject fieldName = convertKey(jp);
|
167
|
+
jp.nextToken();
|
168
|
+
result.fastASet(fieldName, deserialize(jp, ctxt));
|
169
|
+
} while (jp.nextToken() != JsonToken.END_OBJECT);
|
170
|
+
return result;
|
171
|
+
}
|
256
172
|
}
|
257
173
|
|