1919import java .io .InputStreamReader ;
2020import java .io .Reader ;
2121import java .util .ArrayList ;
22- import java .util .Deque ;
2322import java .util .LinkedHashMap ;
24- import java .util .LinkedList ;
25- import java .util .List ;
26- import java .util .Map ;
2723
2824/**
2925 * Decodes JSON content.
3026 */
3127public class JSONDecoder extends Decoder <Object > {
3228 private int c = EOF ;
3329
34- private Deque <Object > containers = new LinkedList <>();
35-
3630 private StringBuilder valueBuilder = new StringBuilder ();
3731
3832 private static final String TRUE = "true" ;
@@ -47,31 +41,9 @@ public Object read(Reader reader) throws IOException {
4741
4842 reader = new BufferedReader (reader );
4943
50- Object value = null ;
51-
5244 c = reader .read ();
5345
54- skipWhitespace (reader );
55-
56- while (c != EOF ) {
57- if (c == ']' || c == '}' ) {
58- value = containers .pop ();
59-
60- c = reader .read ();
61- } else if (c == ',' ) {
62- c = reader .read ();
63- } else {
64- value = readValue (reader );
65- }
66-
67- skipWhitespace (reader );
68- }
69-
70- if (!containers .isEmpty ()) {
71- throw new IOException ("Unterminated container." );
72- }
73-
74- return value ;
46+ return readValue (reader );
7547 }
7648
7749 /**
@@ -112,88 +84,103 @@ public Iterable<Object> readAll(Reader reader) throws IOException {
11284 return (Iterable <Object >)read (reader );
11385 }
11486
115- private void skipWhitespace (Reader reader ) throws IOException {
116- while (c != EOF && Character .isWhitespace (c )) {
117- c = reader .read ();
118- }
119- }
120-
121- @ SuppressWarnings ("unchecked" )
12287 private Object readValue (Reader reader ) throws IOException {
123- var container = containers .peek ();
124-
125- // If the current container is a map, read the key
126- String key ;
127- if (container instanceof Map ) {
128- if (c != '"' ) {
129- throw new IOException ("Invalid key." );
130- }
131-
132- key = readString (reader );
133-
134- skipWhitespace (reader );
135-
136- if (c != ':' ) {
137- throw new IOException ("Missing colon." );
138- }
139-
140- c = reader .read ();
88+ skipWhitespace (reader );
14189
142- skipWhitespace (reader );
143- } else {
144- key = null ;
90+ if (c == EOF ) {
91+ throw new IOException ("Unexpected end of stream." );
14592 }
14693
147- // Read the value
148- Object value ;
14994 if (c == '"' ) {
150- value = readString (reader );
95+ return readString (reader );
15196 } else if (c == '-' || Character .isDigit (c )) {
152- value = readNumber (reader );
97+ return readNumber (reader );
15398 } else if (c == TRUE .charAt (0 )) {
15499 readLiteral (reader , TRUE );
155100
156- value = Boolean .TRUE ;
101+ return Boolean .TRUE ;
157102 } else if (c == FALSE .charAt (0 )) {
158103 readLiteral (reader , FALSE );
159104
160- value = Boolean .FALSE ;
161- } else if (c == NULL .charAt (0 )) {
162- readLiteral (reader , NULL );
163-
164- value = null ;
105+ return Boolean .FALSE ;
165106 } else if (c == '[' ) {
166- value = new ArrayList <>();
107+ var list = new ArrayList <>();
167108
168- containers .push (value );
109+ c = reader .read ();
110+
111+ do {
112+ list .add (readValue (reader ));
113+
114+ skipWhitespace (reader );
115+
116+ if (c == ',' ) {
117+ c = reader .read ();
118+ }
119+ } while (c != ']' );
120+
121+ if (c != ']' ) {
122+ throw new IOException ("Unterminated array." );
123+ }
169124
170125 c = reader .read ();
126+
127+ return list ;
171128 } else if (c == '{' ) {
172- value = new LinkedHashMap <>();
129+ var map = new LinkedHashMap <String , Object >();
130+
131+ c = reader .read ();
132+
133+ do {
134+ skipWhitespace (reader );
135+
136+ if (c != '"' ) {
137+ throw new IOException ("Invalid key." );
138+ }
139+
140+ var key = readString (reader );
141+
142+ skipWhitespace (reader );
143+
144+ if (c != ':' ) {
145+ throw new IOException ("Missing colon." );
146+ }
147+
148+ c = reader .read ();
149+
150+ map .put (key , readValue (reader ));
173151
174- containers .push (value );
152+ skipWhitespace (reader );
153+
154+ if (c == ',' ) {
155+ c = reader .read ();
156+ }
157+ } while (c != '}' );
158+
159+ if (c != '}' ) {
160+ throw new IOException ("Unterminated array." );
161+ }
175162
176163 c = reader .read ();
164+
165+ return map ;
166+ } else if (c == NULL .charAt (0 )) {
167+ readLiteral (reader , NULL );
168+
169+ return null ;
177170 } else {
178171 throw new IOException (String .format ("Unexpected character (0x%04X)." , c ));
179172 }
173+ }
180174
181- // Add the value to the current container
182- if (container != null ) {
183- if (key != null ) {
184- ((Map <String , Object >)container ).put (key , value );
185- } else {
186- ((List <Object >)container ).add (value );
187- }
175+ private void skipWhitespace (Reader reader ) throws IOException {
176+ while (c != EOF && Character .isWhitespace (c )) {
177+ c = reader .read ();
188178 }
189-
190- return value ;
191179 }
192180
193181 private String readString (Reader reader ) throws IOException {
194182 valueBuilder .setLength (0 );
195183
196- // Move to the next character after the opening quotes
197184 c = reader .read ();
198185
199186 while (c != EOF && c != '"' ) {
@@ -248,7 +235,6 @@ private String readString(Reader reader) throws IOException {
248235 throw new IOException ("Unterminated string." );
249236 }
250237
251- // Move to the next character after the closing quotes
252238 c = reader .read ();
253239
254240 return valueBuilder .toString ();
0 commit comments