Skip to content

Commit 4e5226d

Browse files
committed
Update JSONDecoder.
1 parent fb52f85 commit 4e5226d

3 files changed

Lines changed: 71 additions & 85 deletions

File tree

kilo-client/src/main/java/org/httprpc/kilo/io/JSONDecoder.java

Lines changed: 68 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,14 @@
1919
import java.io.InputStreamReader;
2020
import java.io.Reader;
2121
import java.util.ArrayList;
22-
import java.util.Deque;
2322
import 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
*/
3127
public 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();

kilo-client/src/main/java/org/httprpc/kilo/io/TemplateEncoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ private void encode(Object root, Writer writer, Reader reader) throws IOExceptio
491491
}
492492

493493
if (c == EOF) {
494-
throw new IOException("Unexpected end of character stream.");
494+
throw new IOException("Unexpected end of stream.");
495495
}
496496

497497
c = reader.read();

kilo-client/src/test/java/org/httprpc/kilo/io/JSONDecoderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void testArray() throws IOException {
7373
mapOf(entry("x", 1), entry("y", 2.0), entry("z", 3.0))
7474
);
7575

76-
var text = "[\"abc\",\t123,,, true,\n[1, 2.0, 3.0],\n{\"x\": 1, \"y\": 2.0, \"z\": 3.0}]";
76+
var text = "[\"abc\",\t123,\ttrue,\n[1, 2.0, 3.0],\n{\"x\": 1, \"y\": 2.0, \"z\": 3.0}]";
7777

7878
var actual = decode(text);
7979

@@ -96,7 +96,7 @@ public void testObject() throws IOException {
9696
entry("e", mapOf(entry("x", 1), entry("y", 2.0), entry("z", 3.0)))
9797
);
9898

99-
var text = "{\"a\": \"abc\", \"b\":\t123,,, \"c\": true,\n\"d\": [1, 2.0, 3.0],\n\"e\": {\"x\": 1, \"y\": 2.0, \"z\": 3.0}}";
99+
var text = "{\"a\": \"abc\", \"b\":\t123, \"c\": true,\n\"d\": [1, 2.0, 3.0],\n\"e\": {\"x\": 1, \"y\": 2.0, \"z\": 3.0}}";
100100

101101
var actual = decode(text);
102102

0 commit comments

Comments
 (0)