added support for lists (no maps as list elements yet)
This commit is contained in:
parent
e1874de683
commit
b72935960f
4 changed files with 166 additions and 12 deletions
|
|
@ -1,18 +1,22 @@
|
|||
package nl.sander.jsontoy2;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
public class IoReader {
|
||||
private static final int HEX_RADIX = 16;
|
||||
private final InputStream inputStream;
|
||||
private final ByteBuf characterBuffer = new ByteBuf();
|
||||
private final ByteBuf encodedCodePointBuffer = new ByteBuf(4);
|
||||
private final ByteBuffer convertBuffer = ByteBuffer.allocate(4);
|
||||
private boolean escaping = false;
|
||||
private boolean encoded = false;
|
||||
private final ByteBuffer convertBuffer = ByteBuffer.allocate(4);
|
||||
private byte current;
|
||||
private int linecount = 0;
|
||||
private long charcount = 0;
|
||||
|
||||
protected IoReader(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
|
|
@ -55,9 +59,9 @@ public class IoReader {
|
|||
}
|
||||
|
||||
public Character readCharacter() {
|
||||
eat('\"');
|
||||
eatUntil('\"');
|
||||
char currentChar = (char) current;
|
||||
eat('\"');
|
||||
eatUntil('\"');
|
||||
return currentChar;
|
||||
}
|
||||
|
||||
|
|
@ -88,9 +92,57 @@ public class IoReader {
|
|||
return characterBuffer.toString();
|
||||
}
|
||||
|
||||
public List<?> readList() {
|
||||
List<Object> list = new ArrayList<>();
|
||||
|
||||
if (current != '[') {
|
||||
throw new JsonReadException("no list found");
|
||||
}
|
||||
advance();
|
||||
while (current != -1 && current != ']') {
|
||||
Optional<Object> maybeValue = readValue();
|
||||
if (maybeValue.isEmpty()) {
|
||||
break;
|
||||
} else {
|
||||
list.add(maybeValue.get());
|
||||
eatUntilAny(',');
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private Optional<Object> readValue() {
|
||||
Object value;
|
||||
skipWhitespace();
|
||||
if (current == ']') {
|
||||
return Optional.empty();
|
||||
} else if (current == '[') {
|
||||
value = readList();
|
||||
} else if (current == '{') {
|
||||
value = readMap();
|
||||
} else if (current == '\"') {
|
||||
value = readString();
|
||||
} else if (current == 'T' || current == 't' || current == 'F' || current == 'f') {
|
||||
value = readBoolean();
|
||||
} else {
|
||||
String numeric = readNumeric();
|
||||
double doubleValue = Double.parseDouble(numeric);
|
||||
if ((int) doubleValue == doubleValue) {
|
||||
value = (int) doubleValue;
|
||||
} else {
|
||||
value = doubleValue;
|
||||
}
|
||||
}
|
||||
return Optional.of(value);
|
||||
}
|
||||
|
||||
private Map<?, ?> readMap() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public String readString() {
|
||||
eat('\"');
|
||||
eatUntil('\"');
|
||||
|
||||
characterBuffer.clear();
|
||||
boolean endOfString = false;
|
||||
|
|
@ -134,9 +186,6 @@ public class IoReader {
|
|||
}
|
||||
advance();
|
||||
}
|
||||
if (current != -1) {
|
||||
advance();
|
||||
}
|
||||
|
||||
return characterBuffer.toString();
|
||||
}
|
||||
|
|
@ -152,6 +201,7 @@ public class IoReader {
|
|||
void advance() {
|
||||
try {
|
||||
current = (byte) inputStream.read();
|
||||
System.out.println((charcount++) + ":" + (char) current);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
|
@ -170,7 +220,7 @@ public class IoReader {
|
|||
}
|
||||
}
|
||||
|
||||
String eat(char until) {
|
||||
String eatUntil(char until) {
|
||||
characterBuffer.clear();
|
||||
|
||||
while (current > -1 && (current != until | Character.isWhitespace(current))) {
|
||||
|
|
@ -180,4 +230,24 @@ public class IoReader {
|
|||
advance();
|
||||
return characterBuffer.toString();
|
||||
}
|
||||
|
||||
String eatUntilAny(char... untilOrrChars) {
|
||||
characterBuffer.clear();
|
||||
|
||||
while (current > -1 && (!contains(untilOrrChars, current) | Character.isWhitespace(current))) {
|
||||
characterBuffer.add(current);
|
||||
advance();
|
||||
}
|
||||
advance();
|
||||
return characterBuffer.toString();
|
||||
}
|
||||
|
||||
private boolean contains(char[] chars, byte search) {
|
||||
for (char aChar : chars) {
|
||||
if (search == aChar) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import nl.sander.jsontoy2.readers.*;
|
|||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ public class JsonReader {
|
|||
return readers.get(type);
|
||||
}
|
||||
|
||||
public static <T> void register(Class<T> type, JsonObjectReader<T> objectReader) {
|
||||
static <T> void register(Class<T> type, JsonObjectReader<T> objectReader) {
|
||||
readers.put(type, objectReader);
|
||||
}
|
||||
|
||||
|
|
@ -56,5 +57,6 @@ public class JsonReader {
|
|||
register(char.class, new CharReader());
|
||||
register(String.class, new StringReader());
|
||||
register(LocalDateTime.class, new LocalDateTimeReader());
|
||||
register(List.class, new ListReader());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
src/main/java/nl/sander/jsontoy2/readers/ListReader.java
Normal file
14
src/main/java/nl/sander/jsontoy2/readers/ListReader.java
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package nl.sander.jsontoy2.readers;
|
||||
|
||||
import nl.sander.jsontoy2.IoReader;
|
||||
import nl.sander.jsontoy2.JsonObjectReader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ListReader implements JsonObjectReader<List> {
|
||||
@Override
|
||||
public List<?> read(IoReader ioReader) {
|
||||
return ioReader.readList();
|
||||
}
|
||||
}
|
||||
68
src/test/java/nl/sander/jsontoy2/Lists.java
Normal file
68
src/test/java/nl/sander/jsontoy2/Lists.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package nl.sander.jsontoy2;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Lists {
|
||||
|
||||
@Test
|
||||
public void emptyList() {
|
||||
List<String> list = JsonReader.read(List.class, "[]");
|
||||
assertEquals(new ArrayList<>(), list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleStringList() {
|
||||
List<String> list = JsonReader.read(List.class, "[\"hello jason\"]");
|
||||
assertEquals(Collections.singletonList("hello jason"), list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleStringList() {
|
||||
List<String> list = JsonReader.read(List.class, "[\"hello\" , \"jason\"]");
|
||||
List<String> expected = Arrays.asList("hello", "jason");
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleStrings_noComma_error() {
|
||||
List<String> list = JsonReader.read(List.class, "[\"hello\" \"jason\"]");
|
||||
List<String> expected = Collections.singletonList("hello");
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleInt() {
|
||||
List<Integer> list = JsonReader.read(List.class, "[1]");
|
||||
List<Integer> expected = Collections.singletonList(1);
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleInts() {
|
||||
List<Integer> list = JsonReader.read(List.class, "[1,2]");
|
||||
List<Integer> expected = Arrays.asList(1,2);
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intDoubleBooleanString() {
|
||||
List<Integer> list = JsonReader.read(List.class, "[1,2.5,false,\"hello jason\"]");
|
||||
List<?> expected = Arrays.asList(1,2.5,false,"hello jason");
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedList() {
|
||||
List<Integer> list = JsonReader.read(List.class, "[[],[]]");
|
||||
List<?> expected = Arrays.asList(List.of(), List.of());
|
||||
assertEquals(expected, list);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue