17
17
package org .springframework .boot .json ;
18
18
19
19
import java .util .ArrayList ;
20
+ import java .util .Arrays ;
20
21
import java .util .LinkedHashMap ;
21
22
import java .util .List ;
22
23
import java .util .Map ;
@@ -123,38 +124,33 @@ private static String trimEdges(String string, char leadingChar, char trailingCh
123
124
124
125
private List <String > tokenize (String json ) {
125
126
List <String > list = new ArrayList <>();
126
- int index = 0 ;
127
- int inObject = 0 ;
128
- int inList = 0 ;
129
- boolean inValue = false ;
130
- boolean inEscape = false ;
127
+ Tracking tracking = new Tracking ();
131
128
StringBuilder build = new StringBuilder ();
129
+ int index = 0 ;
132
130
while (index < json .length ()) {
133
- char current = json .charAt (index );
134
- if (inEscape ) {
135
- build .append (current );
131
+ char ch = json .charAt (index );
132
+ if (tracking . in ( Tracked . ESCAPE ) ) {
133
+ build .append (ch );
136
134
index ++;
137
- inEscape = false ;
135
+ tracking . set ( Tracked . ESCAPE , 0 ) ;
138
136
continue ;
139
137
}
140
- switch (current ) {
141
- case '{' -> inObject ++;
142
- case '}' -> inObject --;
143
- case '[' -> inList ++;
144
- case ']' -> inList --;
145
- }
146
- if (current == '"' ) {
147
- inValue = !inValue ;
138
+ switch (ch ) {
139
+ case '{' -> tracking .update (Tracked .OBJECT , +1 );
140
+ case '}' -> tracking .update (Tracked .OBJECT , -1 );
141
+ case '[' -> tracking .update (Tracked .LIST , +1 );
142
+ case ']' -> tracking .update (Tracked .LIST , -1 );
143
+ case '"' -> tracking .toggle (Tracked .VALUE );
148
144
}
149
- if (current == ',' && inObject == 0 && inList == 0 && ! inValue ) {
145
+ if (ch == ',' && ! tracking . in ( Tracked . OBJECT , Tracked . LIST , Tracked . VALUE ) ) {
150
146
list .add (build .toString ());
151
147
build .setLength (0 );
152
148
}
153
- else if (current == '\\' ) {
154
- inEscape = true ;
149
+ else if (ch == '\\' ) {
150
+ tracking . set ( Tracked . ESCAPE , 1 ) ;
155
151
}
156
152
else {
157
- build .append (current );
153
+ build .append (ch );
158
154
}
159
155
index ++;
160
156
}
@@ -164,4 +160,36 @@ else if (current == '\\') {
164
160
return list ;
165
161
}
166
162
163
+ private static final class Tracking {
164
+
165
+ private final int [] counts = new int [Tracked .values ().length ];
166
+
167
+ boolean in (Tracked ... tracked ) {
168
+ return Arrays .stream (tracked ).mapToInt (this ::get ).anyMatch ((i ) -> i > 0 );
169
+ }
170
+
171
+ void toggle (Tracked tracked ) {
172
+ set (tracked , (get (tracked ) != 0 ) ? 0 : 1 );
173
+ }
174
+
175
+ void update (Tracked tracked , int delta ) {
176
+ set (tracked , get (tracked ) + delta );
177
+ }
178
+
179
+ private int get (Tracked tracked ) {
180
+ return this .counts [tracked .ordinal ()];
181
+ }
182
+
183
+ void set (Tracked tracked , int count ) {
184
+ this .counts [tracked .ordinal ()] = count ;
185
+ }
186
+
187
+ }
188
+
189
+ private enum Tracked {
190
+
191
+ OBJECT , LIST , VALUE , ESCAPE
192
+
193
+ }
194
+
167
195
}
0 commit comments