24
24
import java .util .Map ;
25
25
import java .util .function .BiConsumer ;
26
26
import java .util .function .Consumer ;
27
+ import java .util .function .Predicate ;
27
28
29
+ import org .springframework .boot .json .JsonWriter .MemberPath ;
30
+ import org .springframework .boot .json .JsonWriter .NameProcessor ;
31
+ import org .springframework .boot .json .JsonWriter .ValueProcessor ;
32
+ import org .springframework .boot .util .LambdaSafe ;
28
33
import org .springframework .util .Assert ;
29
34
import org .springframework .util .ObjectUtils ;
35
+ import org .springframework .util .StringUtils ;
30
36
import org .springframework .util .function .ThrowingConsumer ;
31
37
32
38
/**
@@ -40,6 +46,10 @@ class JsonValueWriter {
40
46
41
47
private final Appendable out ;
42
48
49
+ private MemberPath path = MemberPath .ROOT ;
50
+
51
+ private final Deque <JsonWriterFiltersAndProcessors > filtersAndProcessors = new ArrayDeque <>();
52
+
43
53
private final Deque <ActiveSeries > activeSeries = new ArrayDeque <>();
44
54
45
55
/**
@@ -50,6 +60,14 @@ class JsonValueWriter {
50
60
this .out = out ;
51
61
}
52
62
63
+ void pushProcessors (JsonWriterFiltersAndProcessors jsonProcessors ) {
64
+ this .filtersAndProcessors .addLast (jsonProcessors );
65
+ }
66
+
67
+ void popProcessors () {
68
+ this .filtersAndProcessors .removeLast ();
69
+ }
70
+
53
71
/**
54
72
* Write a name value pair, or just a value if {@code name} is {@code null}.
55
73
* @param <N> the name type in the pair
@@ -82,6 +100,7 @@ <N, V> void write(N name, V value) {
82
100
* @param value the value to write
83
101
*/
84
102
<V > void write (V value ) {
103
+ value = processValue (value );
85
104
if (value == null ) {
86
105
append ("null" );
87
106
}
@@ -119,7 +138,7 @@ else if (value instanceof Number || value instanceof Boolean) {
119
138
*/
120
139
void start (Series series ) {
121
140
if (series != null ) {
122
- this .activeSeries .push (new ActiveSeries ());
141
+ this .activeSeries .push (new ActiveSeries (series ));
123
142
append (series .openChar );
124
143
}
125
144
}
@@ -164,8 +183,10 @@ <E> void writeElements(Consumer<Consumer<E>> elements) {
164
183
<E > void writeElement (E element ) {
165
184
ActiveSeries activeSeries = this .activeSeries .peek ();
166
185
Assert .notNull (activeSeries , "No series has been started" );
167
- activeSeries .appendCommaIfRequired ();
186
+ this .path = activeSeries .updatePath (this .path );
187
+ activeSeries .incrementIndexAndAddCommaIfRequired ();
168
188
write (element );
189
+ this .path = activeSeries .restorePath (this .path );
169
190
}
170
191
171
192
/**
@@ -196,12 +217,17 @@ <N, V> void writePairs(Consumer<BiConsumer<N, V>> pairs) {
196
217
}
197
218
198
219
private <N , V > void writePair (N name , V value ) {
199
- ActiveSeries activeSeries = this .activeSeries .peek ();
200
- Assert .notNull (activeSeries , "No series has been started" );
201
- activeSeries .appendCommaIfRequired ();
202
- writeString (name );
203
- append (":" );
204
- write (value );
220
+ this .path = this .path .child (name .toString ());
221
+ if (!isFilteredPath ()) {
222
+ String processedName = processName (name .toString ());
223
+ ActiveSeries activeSeries = this .activeSeries .peek ();
224
+ Assert .notNull (activeSeries , "No series has been started" );
225
+ activeSeries .incrementIndexAndAddCommaIfRequired ();
226
+ writeString (processedName );
227
+ append (":" );
228
+ write (value );
229
+ }
230
+ this .path = this .path .parent ();
205
231
}
206
232
207
233
private void writeString (Object value ) {
@@ -256,6 +282,48 @@ private void append(char ch) {
256
282
}
257
283
}
258
284
285
+ private boolean isFilteredPath () {
286
+ for (JsonWriterFiltersAndProcessors filtersAndProcessors : this .filtersAndProcessors ) {
287
+ for (Predicate <MemberPath > pathFilter : filtersAndProcessors .pathFilters ()) {
288
+ if (pathFilter .test (this .path )) {
289
+ return true ;
290
+ }
291
+ }
292
+ }
293
+ return false ;
294
+ }
295
+
296
+ private String processName (String name ) {
297
+ for (JsonWriterFiltersAndProcessors filtersAndProcessors : this .filtersAndProcessors ) {
298
+ for (NameProcessor nameProcessor : filtersAndProcessors .nameProcessors ()) {
299
+ name = processName (name , nameProcessor );
300
+ }
301
+ }
302
+ return name ;
303
+ }
304
+
305
+ private String processName (String name , NameProcessor nameProcessor ) {
306
+ name = nameProcessor .processName (this .path , name );
307
+ Assert .state (StringUtils .hasLength (name ), "NameProcessor " + nameProcessor + " returned an empty result" );
308
+ return name ;
309
+ }
310
+
311
+ private <V > V processValue (V value ) {
312
+ for (JsonWriterFiltersAndProcessors filtersAndProcessors : this .filtersAndProcessors ) {
313
+ for (ValueProcessor <?> valueProcessor : filtersAndProcessors .valueProcessors ()) {
314
+ value = processValue (value , valueProcessor );
315
+ }
316
+ }
317
+ return value ;
318
+ }
319
+
320
+ @ SuppressWarnings ({ "unchecked" , "unchecked" })
321
+ private <V > V processValue (V value , ValueProcessor <?> valueProcessor ) {
322
+ return (V ) LambdaSafe .callback (ValueProcessor .class , valueProcessor , this .path , value )
323
+ .invokeAnd ((call ) -> call .processValue (this .path , value ))
324
+ .get (value );
325
+ }
326
+
259
327
/**
260
328
* A series of items that can be written to the JSON output.
261
329
*/
@@ -287,16 +355,27 @@ enum Series {
287
355
*/
288
356
private final class ActiveSeries {
289
357
290
- private boolean commaRequired ;
358
+ private final Series series ;
359
+
360
+ private int index ;
361
+
362
+ private ActiveSeries (Series series ) {
363
+ this .series = series ;
364
+ }
365
+
366
+ MemberPath updatePath (MemberPath path ) {
367
+ return (this .series != Series .ARRAY ) ? path : path .child (this .index );
368
+ }
291
369
292
- private ActiveSeries () {
370
+ MemberPath restorePath (MemberPath path ) {
371
+ return (this .series != Series .ARRAY ) ? path : path .parent ();
293
372
}
294
373
295
- void appendCommaIfRequired () {
296
- if (this .commaRequired ) {
374
+ void incrementIndexAndAddCommaIfRequired () {
375
+ if (this .index > 0 ) {
297
376
append (',' );
298
377
}
299
- this .commaRequired = true ;
378
+ this .index ++ ;
300
379
}
301
380
302
381
}
0 commit comments