11package io .vertx .core .json .jackson .v3 ;
22
3+ import io .netty .buffer .ByteBufInputStream ;
34import 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 ;
49import io .vertx .core .json .DecodeException ;
510import io .vertx .core .json .EncodeException ;
611import io .vertx .core .json .JsonArray ;
712import io .vertx .core .json .JsonObject ;
813import 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 .*;
1315import tools .jackson .core .io .SegmentedStringWriter ;
1416import tools .jackson .core .json .JsonFactory ;
17+ import tools .jackson .core .json .JsonFactoryBuilder ;
18+ import tools .jackson .core .json .JsonReadFeature ;
1519import 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 .*;
2024import java .math .BigDecimal ;
2125import java .math .BigInteger ;
2226import 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
2829import static io .vertx .core .json .impl .JsonUtil .BASE64_DECODER ;
2930import static io .vertx .core .json .impl .JsonUtil .BASE64_ENCODER ;
3031import static java .time .format .DateTimeFormatter .ISO_INSTANT ;
3132
3233public 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