got arrays working

This commit is contained in:
Sander Hautvast 2020-08-06 15:50:57 +02:00
parent c650834d3b
commit 59fbbe904a
7 changed files with 148 additions and 35 deletions

View file

@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -52,7 +53,7 @@ public class JavaObjectReaderFactory {
private static CtMethod createReadJsonMethod(CtClass serializerClass, Class<?> type) { private static CtMethod createReadJsonMethod(CtClass serializerClass, Class<?> type) {
try { try {
String readMethodBodySource = createReadMethodBodySource(type); String readMethodBodySource = createReadMethodBodySource(type);
// System.out.println(readMethodBodySource); System.out.println(readMethodBodySource);
return CtNewMethod.make(Modifier.PUBLIC, OBJECT_CLASS, "read", PARSER_PARAM, NO_EXCEPTIONS, readMethodBodySource, serializerClass); return CtNewMethod.make(Modifier.PUBLIC, OBJECT_CLASS, "read", PARSER_PARAM, NO_EXCEPTIONS, readMethodBodySource, serializerClass);
} catch (CannotCompileException e) { } catch (CannotCompileException e) {
throw new ClassCreationException(e); throw new ClassCreationException(e);
@ -99,13 +100,24 @@ public class JavaObjectReaderFactory {
return "getFloat(\"" + fieldName + "\",object)"; return "getFloat(\"" + fieldName + "\",object)";
} else if (fieldType == double.class) { } else if (fieldType == double.class) {
return "getDouble(\"" + fieldName + "\",object)"; return "getDouble(\"" + fieldName + "\",object)";
} else if (Set.class.isAssignableFrom(fieldType)) {
return "getSet(\"" + fieldName + "\",object)";
} else { } else {
return "(" + fieldType.getName() + ")(object.get(\"" + fieldName + "\"))"; String fieldTypeName = field.getType().getName();
if (Set.class.isAssignableFrom(fieldType)) {
return "(" + fieldTypeName + ")getSet(\"" + fieldName + "\"," + fieldTypeName + ".class,object)";
} else if (List.class.isAssignableFrom(fieldType)) {
return "(" + fieldTypeName + ")getList(\"" + fieldName + "\"," + fieldTypeName + ".class,object)";
} else if (fieldType.isArray()) {
return "(" + format(fieldTypeName) + "[])getArray(\"" + fieldName + "\"," + format(fieldTypeName) + ".class,object)";
} else {
return "(" + fieldTypeName + ")(object.get(\"" + fieldName + "\"))";
}
} }
} }
private static String format(String arrayTypeExpr) {
return arrayTypeExpr.substring(2).substring(0, arrayTypeExpr.length() - 3);
}
//should be reinstated //should be reinstated
private static String genericType(CtField field) { private static String genericType(CtField field) {
try { try {

View file

@ -1,9 +1,9 @@
package nl.sander.jsontoy2; package nl.sander.jsontoy2;
import java.util.HashSet; import java.lang.reflect.Array;
import java.util.List; import java.lang.reflect.Constructor;
import java.util.Map; import java.lang.reflect.InvocationTargetException;
import java.util.Set; import java.util.*;
/** /**
* Base class for generated readers * Base class for generated readers
@ -49,9 +49,64 @@ public abstract class JsonValueReader<T> {
return value == null ? 0D : (Double) value; return value == null ? 0D : (Double) value;
} }
protected Set<?> getSet(String fieldName, Map<String, ?> values) { /*
Object value = values.get(fieldName); * Creates a Set type for any implementation of it (that the containing bean needs),
return value == null ? null : new HashSet<>((List<?>) value); * unless it has no constructor using a java.util.Collection as single parameter.
*
* returntype is generic Set, object needs cast afterwards in generated code
*/
protected Set<?> getSet(String fieldName, Class<? extends Set<?>> type, Map<String, ?> values) {
List<?> value = (List<?>) values.get(fieldName);
if (value == null) {
return null;
} else {
try {
if (type.equals(Set.class)) {
return new HashSet<>(value);
} else {
Constructor<? extends Set<?>> constructor = type.getConstructor(Collection.class);
return constructor.newInstance(value);
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new JsonParseException(e);
}
}
} }
/*
* Creates a List type for any implementation of it (that the containing bean needs),
* unless it has no constructor using a java.util.Collection as single parameter.
*
* returntype is generic List, needs cast afterwards in generated code
*/
protected List<?> getList(String fieldName, Class<?> listImplType, Map<String, ?> values) {
List<?> value = (List<?>) values.get(fieldName);
if (value == null) {
return null;
} else if (listImplType == ArrayList.class || listImplType.equals(List.class)) {
return value;
} else {
try {
Constructor<?> constructor = listImplType.getConstructor(Collection.class);
return (List<?>) constructor.newInstance(value);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new JsonParseException(e);
}
}
}
protected Object getArray(String fieldName, Class<?> arrayType, Map<String, ?> values) {
List<?> value = (List<?>) values.get(fieldName);
if (value == null) {
return new Object[]{};
} else {
Object[] array = (Object[]) Array.newInstance(arrayType, value.size());
int index = 0;
for (Object element : value) {
array[index] = value.get(index++);
}
//TODO this can probably be done smarter
return array;
}
}
} }

View file

@ -148,7 +148,7 @@ public class Parser extends Lexer {
skipWhitespace(); skipWhitespace();
final Maybe<Object> maybeValue; final Maybe<Object> maybeValue;
try { try {
maybeValue = type == null ? parseValue() : parseValue(type.getDeclaredField(key).getType()); maybeValue = type == null ? parseValue() : Maybe.of(JsonReader.read(type.getDeclaredField(key).getType(), this));
maybeValue.ifPresent(value -> map.put(key, value)); maybeValue.ifPresent(value -> map.put(key, value));
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
throw new JsonParseException(e); throw new JsonParseException(e);

View file

@ -32,7 +32,7 @@ public class ReaderFactory {
static <T> JsonValueReader<?> getReader(Class<T> type) { static <T> JsonValueReader<?> getReader(Class<T> type) {
if (Map.class.isAssignableFrom(type)) { if (Map.class.isAssignableFrom(type)) {
return MAPREADER; return MAPREADER;
} else if (List.class.isAssignableFrom(type) || Set.class.isAssignableFrom(type)) { } else if (List.class.isAssignableFrom(type) || Set.class.isAssignableFrom(type) || type.isArray()) {
return LISTREADER; return LISTREADER;
} else { } else {
return readers.computeIfAbsent(type, k -> { return readers.computeIfAbsent(type, k -> {

View file

@ -5,6 +5,8 @@ import org.junit.jupiter.api.Test;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -89,23 +91,23 @@ public class WrapperObjectTests {
assertEquals(new HashSet<>(Arrays.asList("a", "b")), listBean.getValue()); assertEquals(new HashSet<>(Arrays.asList("a", "b")), listBean.getValue());
} }
// @Test @Test
// public void testIntegerList() { public void testIntegerList() {
// IntegerListBean listBean = JsonReader.read(IntegerListBean.class, "{\"value\": [1,22]}"); IntegerListBean listBean = JsonReader.read(IntegerListBean.class, "{\"value\": [1,22]}");
// assertEquals(Arrays.asList(1, 22), listBean.getValue()); assertEquals(Arrays.asList(1, 22), listBean.getValue());
// } }
//
// @Test
// public void testCharacterList() {
// CharacterListBean listBean = JsonReader.read(CharacterListBean.class, "{\"value\": [\"a\", \"[\", \"^\"]}");
// assertEquals(Arrays.asList('a', '[', '^'), listBean.getValue());
// }
// @Test @Test
// public void testShortList() { public void testCharacterList() {
// ShortListBean listBean = JsonReader.read(ShortListBean.class, "{\"value\": [-1,0,1]}"); CharacterListBean listBean = JsonReader.read(CharacterListBean.class, "{\"value\": [\"a\", \"[\", \"^\"]}");
// assertEquals(Arrays.asList((short) -1, (short) 0, (short) 1), listBean.getValue()); assertEquals(Arrays.asList('a', '[', '^'), listBean.getValue());
// } }
@Test
public void testShortList() {
ShortListBean listBean = JsonReader.read(ShortListBean.class, "{\"value\": [-1,0,1]}");
assertEquals(Arrays.asList((short) -1, (short) 0, (short) 1), listBean.getValue());
}
@Test @Test
public void testBooleanList() { public void testBooleanList() {
@ -113,7 +115,7 @@ public class WrapperObjectTests {
assertEquals(Arrays.asList(true, false), listBean.getValue()); assertEquals(Arrays.asList(true, false), listBean.getValue());
} }
// @Test // @Test
// public void testFloatList() { // public void testFloatList() {
// FloatListBean listBean = JsonReader.read(FloatListBean.class, "{\"value\": [-100.156,78.0]}"); // FloatListBean listBean = JsonReader.read(FloatListBean.class, "{\"value\": [-100.156,78.0]}");
// assertEquals(Arrays.asList(-100.156F, 78.0F), listBean.getValue()); // assertEquals(Arrays.asList(-100.156F, 78.0F), listBean.getValue());
@ -125,11 +127,11 @@ public class WrapperObjectTests {
// assertEquals(Arrays.asList((byte) -100, (byte) 78), listBean.getValue()); // assertEquals(Arrays.asList((byte) -100, (byte) 78), listBean.getValue());
// } // }
// //
// @Test @Test
// public void testDoubleList() { public void testDoubleList() {
// DoubleListBean listBean = JsonReader.read(DoubleListBean.class, "{\"value\": [-100.156,78.0]}"); DoubleListBean listBean = JsonReader.read(DoubleListBean.class, "{\"value\": [-100.156,78.0]}");
// assertEquals(Arrays.asList(-100.156D, 78.0D), listBean.getValue()); assertEquals(Arrays.asList(-100.156D, 78.0D), listBean.getValue());
// } }
@Test @Test
public void testNestedBean() { public void testNestedBean() {
@ -143,4 +145,20 @@ public class WrapperObjectTests {
StringMapBean expected = new StringMapBean("a:", "b", "c:", "d"); StringMapBean expected = new StringMapBean("a:", "b", "c:", "d");
assertEquals(expected, actual); assertEquals(expected, actual);
} }
@Test
public void testLinkedList() {
LinkedListBean actual = JsonReader.read(LinkedListBean.class, "{\"list\": [\"a\"]}");
LinkedList<String> actualList = actual.getList();
assertEquals(List.of("a"), actualList);
}
@Test
public void testArray() {
ArrayBean actual = JsonReader.read(ArrayBean.class, "{\"array\": [\"a\"]}");
assertEquals(1, actual.getArray().length);
assertEquals("a", actual.getArray()[0]);
}
} }

View file

@ -0,0 +1,13 @@
package nl.sander.jsontoy2.beans;
public class ArrayBean {
private String[] array;
public void setArray(String[] array) {
this.array = array;
}
public String[] getArray() {
return array;
}
}

View file

@ -0,0 +1,15 @@
package nl.sander.jsontoy2.beans;
import java.util.LinkedList;
public class LinkedListBean {
private LinkedList<String> list;
public LinkedList<String> getList() {
return list;
}
public void setList(LinkedList<String> list) {
this.list = list;
}
}