Skip to content

Commit 195963d

Browse files
committed
Complete implementation of jackson v3 codec
1 parent 45154ed commit 195963d

4 files changed

Lines changed: 135 additions & 44 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.vertx.tests.jacksonv3;
2+
3+
import io.vertx.core.spi.json.JsonCodec;
4+
import io.vertx.tests.json.JsonCodecTest;
5+
import org.junit.Ignore;
6+
import org.junit.Test;
7+
8+
import java.util.Arrays;
9+
import java.util.Collection;
10+
11+
public class JacksonCodecTest extends JsonCodecTest {
12+
13+
public JacksonCodecTest() {
14+
super(new io.vertx.core.json.jackson.v3.JacksonCodec());
15+
}
16+
}
Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
11
package io.vertx.tests.jacksonv3;
22

3-
import org.junit.Test;
4-
import org.junit.Ignore;
5-
63
public class JsonArrayTest extends io.vertx.tests.json.JsonArrayTest {
7-
8-
@Test
9-
@Ignore
10-
public void testClusterSerializable() {
11-
}
12-
13-
@Test
14-
@Ignore
15-
public void testCreateFromBuffer() {
16-
}
174
}
Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
11
package io.vertx.tests.jacksonv3;
22

3-
import org.junit.Test;
4-
import org.junit.Ignore;
5-
63
public class JsonObjectTest extends io.vertx.tests.json.JsonObjectTest {
7-
8-
@Test
9-
@Ignore
10-
public void testClusterSerializable() {
11-
}
12-
13-
@Test
14-
@Ignore
15-
public void testCreateFromBuffer() {
16-
}
174
}

vertx-core/src/main/java25/io/vertx/core/json/jackson/v3/JacksonCodec.java

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,138 @@
11
package io.vertx.core.json.jackson.v3;
22

3+
import io.netty.buffer.ByteBufInputStream;
34
import io.vertx.core.buffer.Buffer;
5+
import io.vertx.core.impl.SysProps;
6+
import io.vertx.core.internal.buffer.BufferInternal;
7+
import io.vertx.core.internal.logging.Logger;
8+
import io.vertx.core.internal.logging.LoggerFactory;
49
import io.vertx.core.json.DecodeException;
510
import io.vertx.core.json.EncodeException;
611
import io.vertx.core.json.JsonArray;
712
import io.vertx.core.json.JsonObject;
813
import io.vertx.core.spi.json.JsonCodec;
9-
import tools.jackson.core.JsonGenerator;
10-
import tools.jackson.core.JsonParser;
11-
import tools.jackson.core.JsonToken;
12-
import tools.jackson.core.JsonTokenId;
14+
import tools.jackson.core.*;
1315
import tools.jackson.core.io.SegmentedStringWriter;
1416
import tools.jackson.core.json.JsonFactory;
17+
import tools.jackson.core.json.JsonFactoryBuilder;
18+
import tools.jackson.core.json.JsonReadFeature;
1519
import tools.jackson.core.util.BufferRecycler;
20+
import tools.jackson.core.util.ByteArrayBuilder;
21+
import tools.jackson.core.util.DefaultPrettyPrinter;
1622

17-
import java.io.Closeable;
18-
import java.io.IOException;
19-
import java.io.Writer;
23+
import java.io.*;
2024
import java.math.BigDecimal;
2125
import java.math.BigInteger;
2226
import java.time.Instant;
23-
import java.util.ArrayList;
24-
import java.util.LinkedHashMap;
25-
import java.util.List;
26-
import java.util.Map;
27+
import java.util.*;
2728

2829
import static io.vertx.core.json.impl.JsonUtil.BASE64_DECODER;
2930
import static io.vertx.core.json.impl.JsonUtil.BASE64_ENCODER;
3031
import static java.time.format.DateTimeFormatter.ISO_INSTANT;
3132

3233
public class JacksonCodec implements JsonCodec {
3334

34-
private static final JsonFactory factory = new JsonFactory();
35+
private static final Logger log = LoggerFactory.getLogger(io.vertx.core.json.jackson.JacksonCodec.class);
36+
37+
private static JsonFactory buildFactory() {
38+
JsonFactoryBuilder tsfBuilder = JsonFactory.builder();
39+
40+
// Build stream read constraints
41+
StreamReadConstraints.Builder readConstraintsBuilder = StreamReadConstraints.builder();
42+
try {
43+
OptionalInt override = SysProps.JACKSON_DEFAULT_READ_MAX_NESTING_DEPTH.getAsInt();
44+
if (override.isPresent()) {
45+
readConstraintsBuilder.maxNestingDepth(override.getAsInt());
46+
}
47+
} catch (IllegalArgumentException e) {
48+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_NESTING_DEPTH.name + " system property value, use " +
49+
StreamReadConstraints.DEFAULT_MAX_DEPTH + " instead");
50+
}
51+
try {
52+
OptionalLong override = SysProps.JACKSON_DEFAULT_READ_MAX_DOC_LEN.getAsLong();
53+
if (override.isPresent()) {
54+
readConstraintsBuilder.maxDocumentLength(override.getAsLong());
55+
}
56+
} catch (IllegalArgumentException e) {
57+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_DOC_LEN.name + " system property value, use " +
58+
StreamReadConstraints.DEFAULT_MAX_DOC_LEN + " instead");
59+
}
60+
try {
61+
OptionalInt override = SysProps.JACKSON_DEFAULT_READ_MAX_NUM_LEN.getAsInt();
62+
if (override.isPresent()) {
63+
readConstraintsBuilder.maxNumberLength(override.getAsInt());
64+
}
65+
} catch (IllegalArgumentException e) {
66+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_NUM_LEN.name + " system property value, use " +
67+
StreamReadConstraints.DEFAULT_MAX_NUM_LEN + " instead");
68+
}
69+
try {
70+
OptionalInt override = SysProps.JACKSON_DEFAULT_READ_MAX_STRING_LEN.getAsInt();
71+
if (override.isPresent()) {
72+
readConstraintsBuilder.maxStringLength(override.getAsInt());
73+
}
74+
} catch (IllegalArgumentException e) {
75+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_STRING_LEN.name + " system property value, use " +
76+
StreamReadConstraints.DEFAULT_MAX_STRING_LEN + " instead");
77+
}
78+
try {
79+
OptionalInt override = SysProps.JACKSON_DEFAULT_READ_MAX_NAME_LEN.getAsInt();
80+
if (override.isPresent()) {
81+
readConstraintsBuilder.maxNameLength(override.getAsInt());
82+
}
83+
} catch (IllegalArgumentException e) {
84+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_NAME_LEN.name + " system property value, use " +
85+
StreamReadConstraints.DEFAULT_MAX_NAME_LEN + " instead");
86+
}
87+
try {
88+
OptionalLong override = SysProps.JACKSON_DEFAULT_READ_MAX_TOKEN_COUNT.getAsLong();
89+
if (override.isPresent()) {
90+
readConstraintsBuilder.maxTokenCount(override.getAsLong());
91+
}
92+
} catch (IllegalArgumentException e) {
93+
log.warn("Invalid " + SysProps.JACKSON_DEFAULT_READ_MAX_TOKEN_COUNT.name + " system property value, use " +
94+
StreamReadConstraints.DEFAULT_MAX_TOKEN_COUNT + " instead");
95+
}
96+
97+
tsfBuilder.streamReadConstraints(readConstraintsBuilder.build());
98+
99+
// Non-standard JSON but we allow C style comments in our JSON
100+
tsfBuilder.configure(JsonReadFeature.ALLOW_JAVA_COMMENTS, true);
101+
102+
return tsfBuilder.build();
103+
}
104+
105+
private static final JsonFactory factory = buildFactory();
35106

36107
public JacksonCodec() {
37108
}
38109

110+
private static JsonParser createParser(Buffer buf) {
111+
return factory.createParser(new ByteBufInputStream(((BufferInternal)buf).getByteBuf()));
112+
}
113+
39114
private static JsonParser createParser(String str) {
40115
return factory.createParser(str);
41116
}
42117

43-
private static JsonGenerator createGenerator(Writer out, boolean pretty) {
44-
JsonGenerator generator = factory.createGenerator(out);
118+
private static ObjectWriteContext owc(boolean pretty) {
45119
if (pretty) {
46-
throw new UnsupportedOperationException();
120+
PrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
121+
return new ObjectWriteContext.Base() {
122+
@Override
123+
public PrettyPrinter getPrettyPrinter() { return prettyPrinter; }
124+
};
125+
} else {
126+
return ObjectWriteContext.empty();
47127
}
48-
return generator;
128+
}
129+
130+
private static JsonGenerator createGenerator(OutputStream out, boolean pretty) {
131+
return factory.createGenerator(owc(pretty), out);
132+
}
133+
134+
private static JsonGenerator createGenerator(Writer out, boolean pretty) {
135+
return factory.createGenerator(owc(pretty), out);
49136
}
50137

51138
@Override
@@ -55,7 +142,7 @@ public <T> T fromString(String json, Class<T> clazz) throws DecodeException {
55142

56143
@Override
57144
public <T> T fromBuffer(Buffer json, Class<T> clazz) throws DecodeException {
58-
throw new UnsupportedOperationException();
145+
return fromParser(createParser(json), clazz);
59146
}
60147

61148
@Override
@@ -80,7 +167,19 @@ public String toString(Object object, boolean pretty) throws EncodeException {
80167

81168
@Override
82169
public Buffer toBuffer(Object object, boolean pretty) throws EncodeException {
83-
throw new UnsupportedOperationException();
170+
BufferRecycler br = factory._getBufferRecycler();
171+
try (ByteArrayBuilder bb = new ByteArrayBuilder(br)) {
172+
JsonGenerator generator = createGenerator(bb, pretty);
173+
encodeJson(object, generator);
174+
generator.close();
175+
byte[] result = bb.toByteArray();
176+
bb.release();
177+
return Buffer.buffer(result);
178+
} catch (Exception e) {
179+
throw new EncodeException(e.getMessage(), e);
180+
} finally {
181+
br.releaseToPool();
182+
}
84183
}
85184

86185
public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeException {
@@ -90,6 +189,8 @@ public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeEx
90189
parser.nextToken();
91190
res = parseAny(parser);
92191
remaining = parser.nextToken();
192+
} catch (JacksonException e) {
193+
throw new DecodeException(e.getMessage(), e);
93194
} catch (IOException e) {
94195
throw new DecodeException(e.getMessage(), e);
95196
} finally {

0 commit comments

Comments
 (0)