diff --git a/src/main/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoder.java b/src/main/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoder.java index fd6b194..988b9ed 100644 --- a/src/main/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoder.java +++ b/src/main/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoder.java @@ -58,7 +58,7 @@ synchronized Object read() { return readBoolean(current); } - if (current == ' ') { + if (shouldSkip(current)) { buffer.advanceSpaces(); return read(); } @@ -66,6 +66,10 @@ synchronized Object read() { return null; } + private static boolean shouldSkip(char current) { + return current == ' ' || current == '\n' || current == '\t' || current == '\r'; + } + private Object readBoolean(char current) { if (current == 't' || current == 'T') { @@ -223,7 +227,7 @@ boolean next() { } void advanceSpaces() { - while (json.charAt(index) == ' ') { + while (shouldSkip(json.charAt(index))) { index++; } } diff --git a/src/main/java/net/jonathangiles/tools/teenyhttpd/json/TeenyJson.java b/src/main/java/net/jonathangiles/tools/teenyhttpd/json/TeenyJson.java index 1eb2e9f..4422535 100644 --- a/src/main/java/net/jonathangiles/tools/teenyhttpd/json/TeenyJson.java +++ b/src/main/java/net/jonathangiles/tools/teenyhttpd/json/TeenyJson.java @@ -84,10 +84,15 @@ public K readCollection(String json, Class collecti * @param type the type of the object to parse * */ + @SuppressWarnings("unchecked") public T readValue(String json, Class type) { if (json == null) return null; + if (type == String.class) { + return (T) json; + } + Object result = new JsonDecoder(json).read(); if (result == null) { @@ -97,6 +102,29 @@ public T readValue(String json, Class type) { return parseObject(result, type); } + @SuppressWarnings("unchecked") + public T readValue(String json, Type type) { + + if (json == null) return null; + + if (type == String.class) { + return (T) json; + } + + Object result = new JsonDecoder(json).read(); + + if (result == null) { + return null; + } + + if (type instanceof Class) { + return (T) parse(result, type); + } + + throw new IllegalStateException("Unsupported type: " + type.getTypeName() + " " + type.getClass().getName()); + } + + /** * Register a custom serializer for the given class. * @@ -210,41 +238,45 @@ private Object parse(Object value, Type target) { throw new IllegalStateException("Unsupported type: " + target.getTypeName() + " " + target.getClass().getName()); } + private String trim(Object value) { + return value.toString().trim(); + } + private Object parsePrimitive(Object value, Class target) { if (target == int.class) { if (value == null) return 0; - return Integer.parseInt(value.toString()); + return Integer.parseInt(trim(value)); } if (target == long.class) { if (value == null) return 0L; - return Long.parseLong(value.toString()); + return Long.parseLong(trim(value)); } if (target == double.class) { if (value == null) return 0.0; - return Double.parseDouble(value.toString()); + return Double.parseDouble(trim(value)); } if (target == float.class) { if (value == null) return 0.0f; - return Float.parseFloat(value.toString()); + return Float.parseFloat(trim(value)); } if (target == boolean.class) { if (value == null) return false; - return Boolean.parseBoolean(value.toString()); + return Boolean.parseBoolean(trim(value)); } throw new IllegalStateException("Unsupported primitive type: " + target.getName()); diff --git a/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyApplicationTest.java b/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyApplicationTest.java index aa1fb21..730f6d5 100644 --- a/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyApplicationTest.java +++ b/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyApplicationTest.java @@ -27,7 +27,6 @@ public class TeenyApplicationTest { private static final int TEST_PORT = 8080; - private static class ProtocolBufferMessageConverter implements MessageConverter { @Override @@ -52,7 +51,7 @@ public void setup() { System.setProperty("banner", "false"); TeenyApplication.start() - .registerMessageConverter(new GsonMessageConverter()) + .registerMessageConverter(new TeenyJsonConverter()) .registerMessageConverter(new ProtocolBufferMessageConverter()) .register(new StoreController()); diff --git a/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyJsonConverter.java b/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyJsonConverter.java new file mode 100644 index 0000000..5fd9109 --- /dev/null +++ b/src/test/java/net/jonathangiles/tools/teenyhttpd/TeenyJsonConverter.java @@ -0,0 +1,35 @@ +package net.jonathangiles.tools.teenyhttpd; + +import net.jonathangiles.tools.teenyhttpd.json.TeenyJson; +import net.jonathangiles.tools.teenyhttpd.model.MessageConverter; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.lang.reflect.Type; + +public class TeenyJsonConverter implements MessageConverter { + + final TeenyJson teenyJson = new TeenyJson(); + + @Override + public String getContentType() { + return "application/json"; + } + + @Override + public void write(Object value, BufferedOutputStream dataOut) throws IOException { + + + if (value instanceof String) { + dataOut.write(((String) value).getBytes()); + return; + } + + dataOut.write(teenyJson.writeValueAsString(value).getBytes()); + } + + @Override + public Object read(String value, Type type) { + return teenyJson.readValue(value, type); + } +} diff --git a/src/test/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoderTest.java b/src/test/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoderTest.java index dfd96b7..1e0732b 100644 --- a/src/test/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoderTest.java +++ b/src/test/java/net/jonathangiles/tools/teenyhttpd/json/JsonDecoderTest.java @@ -349,6 +349,46 @@ void parseDeepObjectTeenyJson() { new ObjectB("Jonathan", 30, new ObjectC("John Doe", 23)))); + System.out.println(json); + + ObjectA objectA = new TeenyJson() + .readValue(json, ObjectA.class); + + System.out.println(objectA); + + Assertions.assertEquals("Alex", objectA.getName()); + Assertions.assertEquals(25, objectA.getAge()); + Assertions.assertTrue(objectA.isDeveloper()); + + ObjectB objectB = objectA.getObjectB(); + + Assertions.assertEquals("Jonathan", objectB.getName()); + Assertions.assertEquals(30, objectB.getAge()); + + ObjectC objectC = objectB.getObjectC(); + + Assertions.assertEquals("John Doe", objectC.getName()); + Assertions.assertEquals(23, objectC.getAge()); + + } + + @Test + void testParseFormattedJson() { + + String json = "{\n" + + " \"objectB\": {\n" + + " \"objectC\": {\n" + + " \"name\": \"John Doe\",\n" + + " \"age\": 23\n" + + " },\n" + + " \"name\": \"Jonathan\",\n" + + " \"age\": 30\n" + + " },\n" + + " \"name\": \"Alex\",\n" + + " \"developer\": true,\n" + + " \"age\": 25\n" + + "}"; + ObjectA objectA = new TeenyJson() .readValue(json, ObjectA.class);