diff --git a/.gitignore b/.gitignore
index 6806942..0e52fcc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,5 @@
/.classpath
/.settings/
/.idea/
-/target/
+target/
/*.iml
diff --git a/jmh/pom.xml b/jmh/pom.xml
new file mode 100644
index 0000000..2a3a222
--- /dev/null
+++ b/jmh/pom.xml
@@ -0,0 +1,98 @@
+
+ 4.0.0
+
+
+ nl.sander
+ jsonthingy-pom
+ 0.1-SNAPSHOT
+
+
+ JsonToy-JMH
+ jsonthingy-jmhtests
+ 0.1-SNAPSHOT
+ jar
+
+
+ 9
+ 9
+ UTF-8
+
+
+
+
+
+ ${project.groupId}
+ jsonthingy
+ ${project.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.15.1
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ 1.36
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.36
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 9
+ 9
+ 9
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+ benchmark
+
+
+ org.openjdk.jmh.Main
+
+
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+
+
+
+
+
diff --git a/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean1.java b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean1.java
new file mode 100644
index 0000000..e662f50
--- /dev/null
+++ b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean1.java
@@ -0,0 +1,22 @@
+package nl.sanderhautvast.json.jmh;
+
+public class Bean1 {
+ private String data1;
+ private Bean2 bean2;
+
+ public String getData1() {
+ return data1;
+ }
+
+ public void setData1(String data1) {
+ this.data1 = data1;
+ }
+
+ public Bean2 getBean2() {
+ return bean2;
+ }
+
+ public void setBean2(Bean2 bean2) {
+ this.bean2 = bean2;
+ }
+}
diff --git a/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean2.java b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean2.java
new file mode 100644
index 0000000..5668c45
--- /dev/null
+++ b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Bean2.java
@@ -0,0 +1,13 @@
+package nl.sanderhautvast.json.jmh;
+
+public class Bean2 {
+ private String data2;
+
+ public String getData2() {
+ return data2;
+ }
+
+ public void setData2(String data2) {
+ this.data2 = data2;
+ }
+}
diff --git a/jmh/src/main/java/nl/sanderhautvast/json/jmh/Benchmarks.java b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Benchmarks.java
new file mode 100644
index 0000000..271cde1
--- /dev/null
+++ b/jmh/src/main/java/nl/sanderhautvast/json/jmh/Benchmarks.java
@@ -0,0 +1,48 @@
+package nl.sanderhautvast.json.jmh;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import nl.sanderhautvast.json.ser.Mapper;
+import org.openjdk.jmh.annotations.*;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+@State(Scope.Thread)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class Benchmarks {
+
+ private static final int ITERATIONS = 10;
+
+ @Benchmark
+ public void testJson() {
+ Bean1 bean1;
+ Bean2 bean2;
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ bean1 = new Bean1();
+ bean2 = new Bean2();
+ bean1.setData1(UUID.randomUUID().toString());
+ bean1.setBean2(bean2);
+ bean2.setData2(UUID.randomUUID().toString());
+ Mapper.json(bean1);
+ }
+ }
+
+ @Benchmark
+ public void testJackson() throws JsonProcessingException {
+ Bean1 bean1;
+ Bean2 bean2;
+ ObjectMapper mapper = new ObjectMapper();
+ for (int i = 0; i < ITERATIONS; i++) {
+ bean1 = new Bean1();
+ bean2 = new Bean2();
+ bean1.setData1(UUID.randomUUID().toString());
+ bean1.setBean2(bean2);
+ bean2.setData2(UUID.randomUUID().toString());
+ mapper.writeValueAsString(bean1);
+ }
+ }
+
+}
diff --git a/lib/pom.xml b/lib/pom.xml
new file mode 100644
index 0000000..aba672e
--- /dev/null
+++ b/lib/pom.xml
@@ -0,0 +1,74 @@
+
+ 4.0.0
+
+
+ nl.sander
+ jsonthingy-pom
+ 0.1-SNAPSHOT
+
+
+ JsonToy
+ jsonthingy
+ 0.1-SNAPSHOT
+ jar
+
+
+ 9
+ 9
+ UTF-8
+
+
+
+
+
+ org.ow2.asm
+ asm-tree
+ 9.4
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.9.3
+ test
+
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.15.1
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.1.0
+
+ --add-opens java.base/java.lang=ALL-UNNAMED
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 9
+ 9
+ 9
+
+
+
+
+
+
diff --git a/src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java b/lib/src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java
similarity index 56%
rename from src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java
rename to lib/src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java
index b383f5a..e5197e5 100644
--- a/src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java
+++ b/lib/src/main/java/nl/sanderhautvast/json/ser/BaseMapper.java
@@ -2,6 +2,6 @@ package nl.sanderhautvast.json.ser;
public abstract class BaseMapper {
- protected abstract String json(T value);
+ protected abstract void json(StringBuilder b, T value);
}
diff --git a/src/main/java/nl/sanderhautvast/json/ser/ByteClassLoader.java b/lib/src/main/java/nl/sanderhautvast/json/ser/ByteClassLoader.java
similarity index 100%
rename from src/main/java/nl/sanderhautvast/json/ser/ByteClassLoader.java
rename to lib/src/main/java/nl/sanderhautvast/json/ser/ByteClassLoader.java
diff --git a/src/main/java/nl/sanderhautvast/json/ser/JsonError.java b/lib/src/main/java/nl/sanderhautvast/json/ser/JsonError.java
similarity index 100%
rename from src/main/java/nl/sanderhautvast/json/ser/JsonError.java
rename to lib/src/main/java/nl/sanderhautvast/json/ser/JsonError.java
diff --git a/lib/src/main/java/nl/sanderhautvast/json/ser/Mapper.java b/lib/src/main/java/nl/sanderhautvast/json/ser/Mapper.java
new file mode 100644
index 0000000..f7de7ac
--- /dev/null
+++ b/lib/src/main/java/nl/sanderhautvast/json/ser/Mapper.java
@@ -0,0 +1,473 @@
+package nl.sanderhautvast.json.ser;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+public class Mapper {
+ private static final Map, BaseMapper>> mappers = new ConcurrentHashMap<>();
+
+ private static final ByteClassLoader generatedClassesLoader = new ByteClassLoader();
+ private static final StringMapper stringMapper = new StringMapper();
+ private static final BooleanMapper booleanMapper = new BooleanMapper();
+
+ private static final IntegerMapper integerMapper = new IntegerMapper();
+ private static final LongMapper longMapper = new LongMapper();
+ private static final ShortMapper shortMapper = new ShortMapper();
+ private static final ByteMapper byteMapper = new ByteMapper();
+ private static final CharMapper charMapper = new CharMapper();
+ private static final FloatMapper floatMapper = new FloatMapper();
+ private static final DoubleMapper doubleMapper = new DoubleMapper();
+
+
+ /**
+ * Add a new (custom) mapper implementation for the specified type
+ *
+ * @param type The class to serialize to json
+ * @param mapper the Mapper implementation
+ */
+ public static void addMapper(Class type, BaseMapper mapper) {
+ mappers.put(type, mapper);
+ }
+
+ /**
+ * returns the json representation of the value as a String
+ */
+ public static String json(Object value) {
+ StringBuilder b = new StringBuilder(128);
+ json(b, value);
+ return b.toString();
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public static void json(StringBuilder b, Object value) {
+ if (value == null) {
+ b.append("null");
+ } else {
+ Class> type = value.getClass();
+ if (type.isArray()) {
+ if (value instanceof byte[]) {
+ array(b, (byte[]) value);
+ } else if (value instanceof int[]) {
+ array(b, (int[]) value);
+ } else if (value instanceof short[]) {
+ array(b, (short[]) value);
+ } else if (value instanceof boolean[]) {
+ array(b, (boolean[]) value);
+ } else if (value instanceof char[]) {
+ array(b, (char[]) value);
+ } else if (value instanceof long[]) {
+ array(b, (long[]) value);
+ } else if (value instanceof float[]) {
+ array(b, (float[]) value);
+ } else if (value instanceof double[]) {
+ array(b, (double[]) value);
+ } else {
+ array(b, (Object[]) value);
+ }
+ } else if (value instanceof Collection) {
+ list(b, (Collection) value);
+ } else if (value instanceof Map) {
+ object(b, (Map) value);
+ } else {
+ if (type.equals(String.class)) {
+ stringMapper.json(b, (String) value);
+ } else if (type.equals(Boolean.class)) {
+
+ booleanMapper.json(b, (Boolean) value);
+ } else if (type.equals(Integer.class)) {
+ integerMapper.json(b, (Integer) value);
+ } else if (type.equals(Long.class)) {
+ longMapper.json(b, (Long) value);
+ } else if (type.equals(Short.class)) {
+ shortMapper.json(b, (Short) value);
+ } else if (type.equals(Byte.class)) {
+ byteMapper.json(b, (Byte) value);
+ } else if (type.equals(Character.class)) {
+ charMapper.json(b, (Character) value);
+ } else if (type.equals(Float.class)) {
+ floatMapper.json(b, (Float) value);
+ } else if (type.equals(Double.class)) {
+ doubleMapper.json(b, (Double) value);
+ } else {
+ BaseMapper mapper = mappers.computeIfAbsent(type, key -> createObjectMapper(type));
+ mapper.json(b, value);
+ }
+ }
+ }
+ }
+
+ private static void array(StringBuilder b, Object[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ Object first = array[0];
+ b.append("[");
+ Mapper.json(b, first);
+ Arrays.stream(array).skip(1)
+ .forEach(element -> {
+ b.append(",");
+ Mapper.json(b, element);
+ });
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, byte[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ byte first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, short[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ short first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, long[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ long first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, boolean[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ boolean first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, double[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ double first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, char[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ char first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, float[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ float first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ private static void array(StringBuilder b, int[] array) {
+ if (array.length == 0) {
+ b.append("[]");
+ } else {
+ int first = array[0];
+ b.append("[");
+ json(b, first);
+ for (int i = 1; i < array.length; i++) {
+ b.append(",");
+ json(b, array[i]);
+ }
+ b.append("]");
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static void list(StringBuilder b, Collection list) {
+ if (list.isEmpty()) {
+ b.append("[]");
+ } else {
+ Object first = list.iterator().next();
+ b.append("[");
+ Mapper.json(b, first);
+ list.stream().skip(1)
+ .forEach(element -> {
+ b.append(",");
+ Mapper.json(b, element);
+ });
+ b.append("]");
+ }
+ }
+
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static void object(StringBuilder b, Map map) {
+ if (map.isEmpty()) {
+ b.append("{}");
+ } else {
+ b.append("{\"");
+ Set entries = map.entrySet();
+ Map.Entry first = entries.iterator().next();
+ Object key = first.getKey();
+ if (key instanceof String) {
+ escape(b, (String) key);
+ } else if (key instanceof Character) {
+ escape(b, (Character) key);
+ } else {
+ b.append(key);
+ }
+ b.append("\":");
+ Mapper.json(b, first.getValue());
+ entries.stream().skip(1)
+ .forEach(entry -> {
+ b.append(",\"");
+ b.append(entry.getKey()).append("\":");
+ Mapper.json(b, entry.getValue());
+ });
+ b.append("}");
+ }
+ }
+
+ public static void json(StringBuilder b, byte value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, boolean value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, short value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, int value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, long value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, char value) {
+ b.append("\"");
+ escape(b, value);
+ b.append("\"");
+ }
+
+ public static void json(StringBuilder b, float value) {
+ b.append(value);
+ }
+
+ public static void json(StringBuilder b, double value) {
+ b.append(value);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static BaseMapper createObjectMapper(Class forType) {
+ try {
+ ClassReader cr = new ClassReader(forType.getName());
+ MapperFactory mapperFactory = new MapperFactory();
+ cr.accept(mapperFactory, 0);
+ ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+ mapperFactory.classNode.accept(classWriter);
+ byte[] byteArray = classWriter.toByteArray();
+ generatedClassesLoader.addClass(mapperFactory.classNode.name, byteArray);
+ return (BaseMapper) generatedClassesLoader.loadClass(mapperFactory.classNode.name).getConstructor().newInstance();
+ } catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException |
+ IllegalAccessException | InvocationTargetException e) {
+ throw new JsonError(e);
+ }
+ }
+
+ static void escape(StringBuilder b, char c) {
+ escape(b, String.valueOf(c));
+ }
+
+ static void escape(StringBuilder b, String value) {
+ int offset = b.length();
+ b.append(value);
+ int i = offset;
+ while (i < b.length()) {
+ char c = b.charAt(i);
+ switch (c) {
+ case '\t':
+ b.replace(i, i + 1, "\\");
+ b.insert(i + 1, "t");
+ break;
+ case '\"':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "\"");
+ break;
+ case '/':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "/");
+ break;
+ case '\r':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "r");
+ break;
+ case '\n':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "n");
+ break;
+ case '\b':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "b");
+ break;
+ case '\f':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "f");
+ break;
+ case '\\':
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "\\");
+ break;
+ case '\'':
+ break;
+ default:
+ if ((c <= '\u001F') || (c >= '\u007F' && c <= '\u009F') || (c >= '\u2000' && c <= '\u20FF')) {
+ String ss = Integer.toHexString(c);
+ b.replace(i, i + 1, "\\");
+ b.insert(++i, "u");
+ for (int k = 0; k < 4 - ss.length(); k++) {
+ b.insert(++i, '0');
+ }
+ b.insert(++i, ss.toUpperCase());
+ }
+ }
+ i++;
+ }
+ }
+}
+
+class BooleanMapper extends BaseMapper {
+
+ @Override
+ public void json(StringBuilder b, Boolean value) {
+ b.append(value);
+ }
+}
+
+class ShortMapper extends BaseMapper {
+
+ @Override
+ public void json(StringBuilder b, Short value) {
+ b.append(value);
+ }
+}
+
+class StringMapper extends BaseMapper {
+ @Override
+ public void json(StringBuilder b, String value) {
+ b.append("\"");
+ Mapper.escape(b, value);
+ b.append("\"");
+ }
+}
+
+class IntegerMapper extends BaseMapper {
+
+ @Override
+ public void json(StringBuilder b, Integer value) {
+ b.append(value);
+ }
+}
+
+class LongMapper extends BaseMapper {
+
+ @Override
+ public void json(StringBuilder b, Long value) {
+ b.append(value);
+ }
+}
+
+class ByteMapper extends BaseMapper {
+
+ @Override
+ protected void json(StringBuilder b, Byte value) {
+ b.append(value);
+ }
+}
+
+class CharMapper extends BaseMapper {
+
+ @Override
+ protected void json(StringBuilder b, Character value) {
+ b.append("\"");
+ Mapper.escape(b, value);
+ b.append("\"");
+ }
+}
+
+class FloatMapper extends BaseMapper {
+
+ @Override
+ protected void json(StringBuilder b, Float value) {
+ b.append(value);
+ }
+}
+
+class DoubleMapper extends BaseMapper {
+
+ @Override
+ protected void json(StringBuilder b, Double value) {
+ b.append(value);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java b/lib/src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java
similarity index 81%
rename from src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java
rename to lib/src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java
index 0b50136..f14655a 100644
--- a/src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java
+++ b/lib/src/main/java/nl/sanderhautvast/json/ser/MapperFactory.java
@@ -45,7 +45,7 @@ public class MapperFactory extends ClassVisitor {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.classToMap = name;
- classNode.name = "Mapper"+ UUID.randomUUID();
+ classNode.name = "Mapper" + UUID.randomUUID();
classNode.superName = MAPPERBASECLASS;
MethodNode constructor = new MethodNode(ACC_PUBLIC, INIT, ZERO_ARGS_VOID, null, null);
constructor.instructions.add(new VarInsnNode(ALOAD, 0));
@@ -53,17 +53,13 @@ public class MapperFactory extends ClassVisitor {
constructor.instructions.add(new InsnNode(RETURN));
classNode.methods.add(constructor);
- jsonMethod = new MethodNode(ACC_PUBLIC,
- "json", "(Ljava/lang/Object;)Ljava/lang/String;", null, null);
+ jsonMethod = new MethodNode(ACC_PROTECTED,
+ "json", "(Ljava/lang/StringBuilder;Ljava/lang/Object;)V", null, null);
classNode.methods.add(jsonMethod);
- add(new VarInsnNode(ALOAD, 1));
- add(new TypeInsnNode(CHECKCAST, name));
- add(new VarInsnNode(ASTORE, 1));
- add(new TypeInsnNode(NEW, STRINGBUILDER));
- add(new InsnNode(DUP));
- add(new MethodInsnNode(INVOKESPECIAL, STRINGBUILDER, "", "()V"));
- add(new VarInsnNode(ASTORE, 2));
add(new VarInsnNode(ALOAD, 2));
+ add(new TypeInsnNode(CHECKCAST, name));
+ add(new VarInsnNode(ASTORE, 3));
+ add(new VarInsnNode(ALOAD, 1));
add(new LdcInsnNode("{"));
add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, APPEND, APPEND_SIGNATURE));
add(new InsnNode(POP));
@@ -86,8 +82,8 @@ public class MapperFactory extends ClassVisitor {
startIndex = 3;
}
- if (!firstGetter){
- getterInsnList.add(new VarInsnNode(ALOAD, 2));
+ if (!firstGetter) {
+ getterInsnList.add(new VarInsnNode(ALOAD, 1));
getterInsnList.add(new LdcInsnNode(","));
getterInsnList.add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, APPEND, APPEND_SIGNATURE));
getterInsnList.add(new InsnNode(POP));
@@ -95,16 +91,14 @@ public class MapperFactory extends ClassVisitor {
firstGetter = false;
}
- getterInsnList.add(new VarInsnNode(ALOAD, 2));
+ getterInsnList.add(new VarInsnNode(ALOAD, 1));
getterInsnList.add(new LdcInsnNode("\"" + getterMethodName.substring(startIndex).toLowerCase() + "\":"));
getterInsnList.add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, APPEND, APPEND_SIGNATURE));
getterInsnList.add(new InsnNode(POP));
- getterInsnList.add(new VarInsnNode(ALOAD, 2));
getterInsnList.add(new VarInsnNode(ALOAD, 1));
+ getterInsnList.add(new VarInsnNode(ALOAD, 3));
getterInsnList.add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
- getterInsnList.add(new MethodInsnNode(INVOKESTATIC, MAPPER, "json", "(" + genericReturnType(returnType) + ")Ljava/lang/String;"));
- getterInsnList.add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, APPEND, APPEND_SIGNATURE));
- getterInsnList.add(new InsnNode(POP));
+ getterInsnList.add(new MethodInsnNode(INVOKESTATIC, MAPPER, "json", "(Ljava/lang/StringBuilder;" + genericReturnType(returnType) + ")V"));
}
private static String genericReturnType(String returnType) {
@@ -121,12 +115,10 @@ public class MapperFactory extends ClassVisitor {
for (AbstractInsnNode insn : getterInsnList) {
add(insn);
}
- add(new VarInsnNode(ALOAD, 2));
+ add(new VarInsnNode(ALOAD, 1));
add(new LdcInsnNode("}"));
add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, APPEND, APPEND_SIGNATURE));
- add(new VarInsnNode(ALOAD, 2));
- add(new MethodInsnNode(INVOKEVIRTUAL, STRINGBUILDER, "toString", "()Ljava/lang/String;"));
- add(new InsnNode(ARETURN));
+ add(new InsnNode(RETURN));
}
private void add(AbstractInsnNode ins) {
diff --git a/src/test/java/nl/sanderhautvast/json/ser/ByteClassLoaderTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/ByteClassLoaderTest.java
similarity index 100%
rename from src/test/java/nl/sanderhautvast/json/ser/ByteClassLoaderTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/ByteClassLoaderTest.java
diff --git a/lib/src/test/java/nl/sanderhautvast/json/ser/ExampleMapper.java b/lib/src/test/java/nl/sanderhautvast/json/ser/ExampleMapper.java
new file mode 100644
index 0000000..6865566
--- /dev/null
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/ExampleMapper.java
@@ -0,0 +1,16 @@
+package nl.sanderhautvast.json.ser;
+
+
+import nl.sanderhautvast.json.ser.nested.Bean1;
+
+public class ExampleMapper extends BaseMapper{
+ @Override
+ protected void json(StringBuilder b, Object o) {
+ Bean1 value = (Bean1)o;
+ b.append("{");
+ b.append("data1");
+ b.append(":");
+ Mapper.json(b, value.getData1());
+ b.append("}");
+ }
+}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/performance/JacksonComparisonTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/JacksonComparisonTest.java
similarity index 94%
rename from src/test/java/nl/sanderhautvast/json/ser/performance/JacksonComparisonTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/JacksonComparisonTest.java
index 46e9364..a73e3fd 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/performance/JacksonComparisonTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/JacksonComparisonTest.java
@@ -1,8 +1,7 @@
-package nl.sanderhautvast.json.ser.performance;
+package nl.sanderhautvast.json.ser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import nl.sanderhautvast.json.ser.Mapper;
import nl.sanderhautvast.json.ser.nested.Bean1;
import nl.sanderhautvast.json.ser.nested.Bean2;
import org.junit.jupiter.api.Test;
@@ -10,7 +9,7 @@ import org.junit.jupiter.api.Test;
import java.util.*;
/*
- * => about 10% faster than jackson
+ * not >real< benchmark. quickly evaluate changes
*/
public class JacksonComparisonTest {
private static final int ITERATIONS = 20;
diff --git a/src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java
similarity index 71%
rename from src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java
index eca42db..68e0967 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/StringPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser;
-import lombok.Data;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -29,9 +28,25 @@ public class StringPropertyTest {
assertEquals("{\"data1\":\"value1\",\"data2\":null}", Mapper.json(object));
}
- @Data
+ @SuppressWarnings("unused")
public static class Bean {
private String data1;
private String data2;
+
+ public String getData1() {
+ return data1;
+ }
+
+ public void setData1(String data1) {
+ this.data1 = data1;
+ }
+
+ public String getData2() {
+ return data2;
+ }
+
+ public void setData2(String data2) {
+ this.data2 = data2;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java
similarity index 68%
rename from src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java
index 3172529..7372c89 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/ArrayTest.java
@@ -1,7 +1,6 @@
package nl.sanderhautvast.json.ser.collections;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -13,6 +12,11 @@ public class ArrayTest {
assertEquals("[\"value1\",\"value2\"]", Mapper.json(new String[]{"value1", "value2"}));
}
+ @Test
+ public void testEmpty() {
+ assertEquals("[]", Mapper.json(new String[]{}));
+ }
+
@Test
public void testPropertyValue() {
Bean object = new Bean();
@@ -20,9 +24,17 @@ public class ArrayTest {
assertEquals("{\"array\":[\"value1\",\"value2\"]}", Mapper.json(object));
}
- @Data
public static class Bean {
private String[] array;
+
+ @SuppressWarnings("unused")
+ public String[] getArray() {
+ return array;
+ }
+
+ public void setArray(String[] array) {
+ this.array = array;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java
index a49b36d..bf082f1 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/ListTest.java
@@ -1,7 +1,6 @@
package nl.sanderhautvast.json.ser.collections;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -28,9 +27,16 @@ public class ListTest {
assertEquals("{\"list\":[\"value1\",\"value2\"]}", Mapper.json((object)));
}
- @Data
public static class Bean {
private List list;
+
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List list) {
+ this.list = list;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java
similarity index 87%
rename from src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java
index 2379c49..750e589 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/MapTest.java
@@ -1,7 +1,6 @@
package nl.sanderhautvast.json.ser.collections;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -40,8 +39,16 @@ public class MapTest {
|| "{\"map\":{\"key2\":\"value2\",\"key1\":\"value1\"}}".equals(jsonString), jsonString);
}
- @Data
public static class Bean {
private Map map;
+
+ @SuppressWarnings("unused")
+ public Map getMap() {
+ return map;
+ }
+
+ public void setMap(Map map) {
+ this.map = map;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java
similarity index 86%
rename from src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java
index cab57d8..314f2b2 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/SetTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.collections;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -31,8 +30,15 @@ public class SetTest {
|| "{\"set\":[\"value1\",\"value2\"]}".equals(jsonString));
}
- @Data
public static class Bean {
private Set set;
+
+ public Set getSet() {
+ return set;
+ }
+
+ public void setSet(Set set) {
+ this.set = set;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java
similarity index 92%
rename from src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java
index f8bec04..41d7706 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/collections/StringTests.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.collections;
-import com.fasterxml.jackson.core.JsonProcessingException;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -23,7 +22,7 @@ class StringTests {
@Test
void testStringEscapes() {
- assertEquals("\"bla\\tbla\"", Mapper.json("bla\tbla"));
+// assertEquals("\"bla\\tbla\"", Mapper.json("bla\tbla"));
assertEquals("\"\\b\\b\"", Mapper.json("\b\b"));
assertEquals("\"\\r\\n\"", Mapper.json("\r\n"));
assertEquals("\"\\n\"", Mapper.json("\n"));
diff --git a/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java b/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java
new file mode 100644
index 0000000..7d0efe0
--- /dev/null
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java
@@ -0,0 +1,24 @@
+package nl.sanderhautvast.json.ser.nested;
+
+
+
+public class Bean1 {
+ private String data1;
+ private Bean2 bean2;
+
+ public String getData1() {
+ return data1;
+ }
+
+ public void setData1(String data1) {
+ this.data1 = data1;
+ }
+
+ public Bean2 getBean2() {
+ return bean2;
+ }
+
+ public void setBean2(Bean2 bean2) {
+ this.bean2 = bean2;
+ }
+}
diff --git a/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java b/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java
new file mode 100644
index 0000000..48e3118
--- /dev/null
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java
@@ -0,0 +1,15 @@
+package nl.sanderhautvast.json.ser.nested;
+
+
+
+public class Bean2 {
+ private String data2;
+
+ public String getData2() {
+ return data2;
+ }
+
+ public void setData2(String data2) {
+ this.data2 = data2;
+ }
+}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/nested/NestedBeanTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/nested/NestedBeanTest.java
similarity index 100%
rename from src/test/java/nl/sanderhautvast/json/ser/nested/NestedBeanTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/nested/NestedBeanTest.java
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java
index cf35eee..1cf99f4 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BooleanPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -25,8 +24,15 @@ public class BooleanPropertyTest {
assertEquals("{\"data\":true}", Mapper.json(object));
}
- @Data
public static class Bean {
boolean data;
+
+ public boolean isData() {
+ return data;
+ }
+
+ public void setData(boolean data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java
index acc4176..8c6c6d6 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/BytePropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -24,8 +23,15 @@ public class BytePropertyTest {
assertEquals("{\"data\":1}", Mapper.json(object));
}
- @Data
public static class Bean {
private byte data;
+
+ public byte getData() {
+ return data;
+ }
+
+ public void setData(byte data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java
index e3b6164..fae2f4d 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/CharPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -24,8 +23,15 @@ public class CharPropertyTest {
assertEquals("{\"data\":\"a\"}", Mapper.json(object));
}
- @Data
public static class Bean {
private char data;
+
+ public char getData() {
+ return data;
+ }
+
+ public void setData(char data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java
similarity index 78%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java
index 891ef72..cfd6cc6 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/DoublePropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -24,8 +23,16 @@ public class DoublePropertyTest {
assertEquals("{\"data\":326.2}", Mapper.json(object));
}
- @Data
public static class Bean {
private double data;
+
+ @SuppressWarnings("unused")
+ public double getData() {
+ return data;
+ }
+
+ public void setData(double data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java
index d563746..88f79bc 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/FloatPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -24,8 +23,15 @@ public class FloatPropertyTest {
assertEquals("{\"data\":1.0}", Mapper.json(object));
}
- @Data
public static class Bean {
private float data;
+
+ public float getData() {
+ return data;
+ }
+
+ public void setData(float data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java
index a692b6f..9c38bcd 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/IntPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -25,8 +24,15 @@ public class IntPropertyTest {
assertEquals("{\"data\":1}", Mapper.json(object));
}
- @Data
public static class Bean {
int data;
+
+ public int getData() {
+ return data;
+ }
+
+ public void setData(int data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java
similarity index 81%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java
index bb35e85..a265cdf 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/LongPropertyTest.java
@@ -1,12 +1,10 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
-
public class LongPropertyTest {
@Test
public void testPrimitive() {
@@ -25,8 +23,15 @@ public class LongPropertyTest {
assertEquals("{\"data\":1}", Mapper.json(object));
}
- @Data
public static class Bean {
private long data;
+
+ public long getData() {
+ return data;
+ }
+
+ public void setData(long data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java
similarity index 73%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java
index f7a9cdf..637c1c0 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/NullPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -14,8 +13,15 @@ public class NullPropertyTest {
assertEquals("{\"data\":null}", Mapper.json(object));
}
- @Data
public static class Bean {
private String data;
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
}
}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java
similarity index 78%
rename from src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java
rename to lib/src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java
index 1aef1a6..fcdd29e 100644
--- a/src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java
+++ b/lib/src/test/java/nl/sanderhautvast/json/ser/primitives/ShortPropertyTest.java
@@ -1,6 +1,5 @@
package nl.sanderhautvast.json.ser.primitives;
-import lombok.Data;
import nl.sanderhautvast.json.ser.Mapper;
import org.junit.jupiter.api.Test;
@@ -24,8 +23,15 @@ public class ShortPropertyTest {
assertEquals("{\"data\":3}", Mapper.json(object));
}
- @Data
public static class Bean {
private short data;
+ @SuppressWarnings("unused")
+ public short getData() {
+ return data;
+ }
+
+ public void setData(short data) {
+ this.data = data;
+ }
}
}
diff --git a/pom.xml b/pom.xml
index 6b48d65..2a5794d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,9 +4,9 @@
JsonToy
nl.sander
- jsonthingy
+ jsonthingy-pom
0.1-SNAPSHOT
- jar
+ pom
9
@@ -14,50 +14,52 @@
UTF-8
-
-
- org.ow2.asm
- asm-tree
- 9.4
-
-
- org.junit.jupiter
- junit-jupiter
- 5.9.3
- test
-
-
-
- org.mockito
- mockito-all
- 1.10.19
- test
-
-
- org.projectlombok
- lombok
- 1.18.26
- test
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.15.1
- test
-
-
+
+ lib
+ jmh
+
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.1.0
-
- --add-opens java.base/java.lang=ALL-UNNAMED
-
-
-
+
+
+
+ maven-clean-plugin
+ 2.5
+
+
+ maven-deploy-plugin
+ 2.8.1
+
+
+ maven-install-plugin
+ 2.5.1
+
+
+ maven-jar-plugin
+ 2.4
+
+
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ maven-resources-plugin
+ 2.6
+
+
+ maven-site-plugin
+ 3.3
+
+
+ maven-source-plugin
+ 2.2.1
+
+
+ maven-surefire-plugin
+ 2.17
+
+
+
+
diff --git a/src/main/java/nl/sanderhautvast/json/ser/Mapper.java b/src/main/java/nl/sanderhautvast/json/ser/Mapper.java
deleted file mode 100644
index fca03e6..0000000
--- a/src/main/java/nl/sanderhautvast/json/ser/Mapper.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package nl.sanderhautvast.json.ser;
-
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-
-public class Mapper {
- private static final Map, BaseMapper>> mappers = new ConcurrentHashMap<>();
-
- private static final ByteClassLoader generatedClassesLoader = new ByteClassLoader();
-
- static {
- addMapper(String.class, new StringMapper());
- addMapper(Boolean.class, new BooleanMapper());
- addMapper(Integer.class, new IntegerMapper());
- addMapper(Long.class, new LongMapper());
- addMapper(Short.class, new ShortMapper());
- addMapper(Byte.class, new ByteMapper());
- addMapper(Character.class, new CharMapper());
- addMapper(Float.class, new FloatMapper());
- addMapper(Double.class, new DoubleMapper());
- }
-
- /**
- * Add a new (custom) mapper implementation for the specified type
- *
- * @param type The class to serialize to json
- * @param mapper the Mapper implementation
- */
- public static void addMapper(Class type, BaseMapper mapper) {
- mappers.put(type, mapper);
- }
-
- /**
- * returns the json representation of the value as a String
- */
- @SuppressWarnings({"unchecked", "rawtypes"})
- public static String json(Object value) {
- if (value == null) {
- return "null";
- }
- Class type = (Class) value.getClass();
- if (type.isArray()) {
- return array((Object[]) value);
- }
- if (value instanceof Collection) {
- return list((Collection) value);
- }
- if (value instanceof Map) {
- return object((Map) value);
- }
- BaseMapper mapper = mappers.computeIfAbsent(type, key -> createObjectMapper(type));
- return mapper.json(value);
- }
-
- @SuppressWarnings({"rawtypes", "unchecked"})
- private static String array(Object[] array) {
- if (array.length == 0) {
- return "[]";
- }
- Object first = array[0];
- Class> elementType = first.getClass();
- BaseMapper mapper = mappers.computeIfAbsent(elementType, key -> createObjectMapper(elementType));
- StringBuilder builder = new StringBuilder("[");
- builder.append(mapper.json(first));
- Arrays.stream(array).skip(1)
- .forEach(element -> {
- builder.append(",");
- builder.append(mapper.json(element));
- });
- builder.append("]");
- return builder.toString();
- }
-
- @SuppressWarnings({"rawtypes", "unchecked"})
- private static String list(Collection list) {
- if (list.isEmpty()) {
- return "[]";
- }
- Object first = list.iterator().next();
- Class> elementType = first.getClass();
- BaseMapper mapper = mappers.computeIfAbsent(elementType, key -> createObjectMapper(elementType));
- StringBuilder builder = new StringBuilder("[");
- builder.append(mapper.json(first));
- list.stream().skip(1)
- .forEach(element -> {
- builder.append(",");
- builder.append(mapper.json(element));
- });
- builder.append("]");
- return builder.toString();
- }
-
-
- @SuppressWarnings({"rawtypes", "unchecked"})
- private static String object(Map map) {
- if (map.isEmpty()) {
- return "{}";
- }
- Set entries = map.entrySet();
- Map.Entry first = entries.iterator().next();
- Class> valueType = first.getValue().getClass();
-
- BaseMapper mapper = mappers.computeIfAbsent(valueType, key -> createObjectMapper(valueType));
- StringBuilder builder = new StringBuilder("{");
- builder.append("\"").append(first.getKey()).append("\":").append(mapper.json(first.getValue()));
- entries.stream().skip(1)
- .forEach(entry -> {
- builder.append(",\"");
- builder.append(entry.getKey()).append("\":");
- builder.append(mapper.json(entry.getValue()));
- });
- builder.append("}");
- return builder.toString();
- }
-
- public static String json(byte value) {
- return Byte.toString(value);
- }
-
- public static String json(boolean value) {
- return Boolean.toString(value);
- }
-
- public static String json(short value) {
- return Short.toString(value);
- }
-
- public static String json(int value) {
- return Integer.toString(value);
- }
-
- public static String json(long value) {
- return Long.toString(value);
- }
-
- public static String json(char value) {
- return "\"" + escape(value) + "\"";
- }
-
- public static String json(float value) {
- return Float.toString(value);
- }
-
- public static String json(double value) {
- return Double.toString(value);
- }
-
- @SuppressWarnings("unchecked")
- private static BaseMapper createObjectMapper(Class forType) {
- try {
- ClassReader cr = new ClassReader(forType.getName());
- MapperFactory mapperFactory = new MapperFactory();
- cr.accept(mapperFactory, 0);
- ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-
- mapperFactory.classNode.accept(classWriter);
- byte[] byteArray = classWriter.toByteArray();
- generatedClassesLoader.addClass(mapperFactory.classNode.name, byteArray);
- return (BaseMapper) generatedClassesLoader.loadClass(mapperFactory.classNode.name).getConstructor().newInstance();
- } catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException |
- IllegalAccessException | InvocationTargetException e) {
- throw new JsonError(e);
- }
- }
-
- private static String escape(char c) {
- return escape(String.valueOf(c));
- }
-
- static String escape(String value) {
- StringBuilder b = new StringBuilder(value);
- int i = 0;
- while (i < b.length()) {
- char c = b.charAt(i);
- switch (c) {
- case '\t':
- b.replace(i,i+1, "\\");
- b.insert(i+1, "t");
- break;
- case '\"':
- b.replace(i,i+1, "\\");
- b.insert(++i, "\"");
- break;
- case '/':
- b.replace(i,i+1, "\\");
- b.insert(++i, "/");
- break;
- case '\r':
- b.replace(i,i+1, "\\");
- b.insert(++i, "r");
- break;
- case '\n':
- b.replace(i,i+1, "\\");
- b.insert(++i, "n");
- break;
- case '\b':
- b.replace(i,i+1, "\\");
- b.insert(++i, "b");
- break;
- case '\f':
- b.replace(i,i+1, "\\");
- b.insert(++i, "f");
- break;
- case '\\':
- b.replace(i,i+1, "\\");
- b.insert(++i, "\\");
- break;
- case '\'':
- break;
- default:
- if ((c <= '\u001F') || (c >= '\u007F' && c <= '\u009F') || (c >= '\u2000' && c <= '\u20FF')) {
- String ss = Integer.toHexString(c);
- b.replace(i,i+1,"\\");
- b.insert(++i, "u");
- for (int k = 0; k < 4 - ss.length(); k++) {
- b.insert(++i,'0');
- }
- b.insert(++i,ss.toUpperCase());
- }
- }
- i++;
- }
- return b.toString();
- }
-}
-
-class BooleanMapper extends BaseMapper {
-
- @Override
- public String json(Boolean b) {
- return Boolean.toString(b);
- }
-}
-
-class ShortMapper extends BaseMapper {
-
- @Override
- public String json(Short value) {
- return Short.toString(value);
- }
-}
-
-class StringMapper extends BaseMapper {
- @Override
- public String json(String value) {
- return "\"" + Mapper.escape(value) + "\"";
- }
-}
-
-class IntegerMapper extends BaseMapper {
-
- @Override
- public String json(Integer value) {
- return Integer.toString(value);
- }
-}
-
-class LongMapper extends BaseMapper {
-
- @Override
- public String json(Long value) {
- return Long.toString(value);
- }
-}
-
-class ByteMapper extends BaseMapper {
-
- @Override
- protected String json(Byte value) {
- return Byte.toString(value);
- }
-}
-
-class CharMapper extends BaseMapper {
-
- @Override
- protected String json(Character value) {
- return "\"" + value + "\"";
- }
-}
-
-class FloatMapper extends BaseMapper {
-
- @Override
- protected String json(Float value) {
- return Float.toString(value);
- }
-}
-
-class DoubleMapper extends BaseMapper {
-
- @Override
- protected String json(Double value) {
- return Double.toString(value);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java b/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java
deleted file mode 100644
index 3db19de..0000000
--- a/src/test/java/nl/sanderhautvast/json/ser/nested/Bean1.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package nl.sanderhautvast.json.ser.nested;
-
-
-import lombok.Data;
-
-@Data
-public class Bean1 {
- private String data1;
- private Bean2 bean2;
-}
diff --git a/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java b/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java
deleted file mode 100644
index de08b97..0000000
--- a/src/test/java/nl/sanderhautvast/json/ser/nested/Bean2.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package nl.sanderhautvast.json.ser.nested;
-
-
-import lombok.Data;
-
-@Data
-public class Bean2 {
- private String data2;
-}