1717package org .springframework .http .codec .json ;
1818
1919import java .io .IOException ;
20+ import java .nio .ByteBuffer ;
2021import java .util .ArrayList ;
2122import java .util .List ;
2223import java .util .function .Function ;
2627import com .fasterxml .jackson .core .JsonProcessingException ;
2728import com .fasterxml .jackson .core .JsonToken ;
2829import com .fasterxml .jackson .core .async .ByteArrayFeeder ;
30+ import com .fasterxml .jackson .core .async .ByteBufferFeeder ;
31+ import com .fasterxml .jackson .core .async .NonBlockingInputFeeder ;
2932import com .fasterxml .jackson .databind .DeserializationContext ;
3033import com .fasterxml .jackson .databind .ObjectMapper ;
3134import com .fasterxml .jackson .databind .deser .DefaultDeserializationContext ;
3235import com .fasterxml .jackson .databind .util .TokenBuffer ;
36+ import com .fasterxml .jackson .dataformat .smile .SmileFactory ;
3337import reactor .core .Exceptions ;
3438import reactor .core .publisher .Flux ;
3539
@@ -54,6 +58,8 @@ final class Jackson2Tokenizer {
5458
5559 private final DeserializationContext deserializationContext ;
5660
61+ private final NonBlockingInputFeeder inputFeeder ;
62+
5763 private final boolean tokenizeArrayElements ;
5864
5965 private final boolean forceUseOfBigDecimal ;
@@ -69,33 +75,32 @@ final class Jackson2Tokenizer {
6975 private TokenBuffer tokenBuffer ;
7076
7177
72- // TODO: change to ByteBufferFeeder when supported by Jackson
73- // See https://github.com/FasterXML/jackson-core/issues/478
74- private final ByteArrayFeeder inputFeeder ;
75-
76-
7778 private Jackson2Tokenizer (JsonParser parser , DeserializationContext deserializationContext ,
7879 boolean tokenizeArrayElements , boolean forceUseOfBigDecimal , int maxInMemorySize ) {
7980
8081 this .parser = parser ;
8182 this .deserializationContext = deserializationContext ;
83+ this .inputFeeder = this .parser .getNonBlockingInputFeeder ();
8284 this .tokenizeArrayElements = tokenizeArrayElements ;
8385 this .forceUseOfBigDecimal = forceUseOfBigDecimal ;
84- this .inputFeeder = (ByteArrayFeeder ) this .parser .getNonBlockingInputFeeder ();
8586 this .maxInMemorySize = maxInMemorySize ;
8687 this .tokenBuffer = createToken ();
8788 }
8889
8990
9091
9192 private List <TokenBuffer > tokenize (DataBuffer dataBuffer ) {
92- int bufferSize = dataBuffer .readableByteCount ();
93- byte [] bytes = new byte [bufferSize ];
94- dataBuffer .read (bytes );
95- DataBufferUtils .release (dataBuffer );
96-
9793 try {
98- this .inputFeeder .feedInput (bytes , 0 , bytes .length );
94+ int bufferSize = dataBuffer .readableByteCount ();
95+ if (this .inputFeeder instanceof ByteBufferFeeder byteBufferFeeder ) {
96+ ByteBuffer byteBuffer = dataBuffer .toByteBuffer ();
97+ byteBufferFeeder .feedInput (byteBuffer );
98+ }
99+ else if (this .inputFeeder instanceof ByteArrayFeeder byteArrayFeeder ) {
100+ byte [] bytes = new byte [bufferSize ];
101+ dataBuffer .read (bytes );
102+ byteArrayFeeder .feedInput (bytes , 0 , bufferSize );
103+ }
99104 List <TokenBuffer > result = parseTokenBufferFlux ();
100105 assertInMemorySize (bufferSize , result );
101106 return result ;
@@ -106,6 +111,9 @@ private List<TokenBuffer> tokenize(DataBuffer dataBuffer) {
106111 catch (IOException ex ) {
107112 throw Exceptions .propagate (ex );
108113 }
114+ finally {
115+ DataBufferUtils .release (dataBuffer );
116+ }
109117 }
110118
111119 private Flux <TokenBuffer > endOfInput () {
@@ -232,7 +240,14 @@ public static Flux<TokenBuffer> tokenize(Flux<DataBuffer> dataBuffers, JsonFacto
232240 ObjectMapper objectMapper , boolean tokenizeArrays , boolean forceUseOfBigDecimal , int maxInMemorySize ) {
233241
234242 try {
235- JsonParser parser = jsonFactory .createNonBlockingByteArrayParser ();
243+ JsonParser parser ;
244+ if (jsonFactory .getFormatName ().equals (SmileFactory .FORMAT_NAME_SMILE )) {
245+ // ByteBufferFeeder is not supported for Smile
246+ parser = jsonFactory .createNonBlockingByteArrayParser ();
247+ }
248+ else {
249+ parser = jsonFactory .createNonBlockingByteBufferParser ();
250+ }
236251 DeserializationContext context = objectMapper .getDeserializationContext ();
237252 if (context instanceof DefaultDeserializationContext ) {
238253 context = ((DefaultDeserializationContext ) context ).createInstance (
0 commit comments