From a947f14f35bbec74b1581377c6a6981f891d95b7 Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Tue, 5 Jan 2016 20:16:06 +0100 Subject: [PATCH] initial commit --- .classpath | 20 + .gradle/2.3/taskArtifacts/cache.properties | 1 + .../2.3/taskArtifacts/cache.properties.lock | Bin 0 -> 17 bytes .gradle/2.3/taskArtifacts/fileHashes.bin | Bin 0 -> 26245 bytes .gradle/2.3/taskArtifacts/fileSnapshots.bin | Bin 0 -> 85825 bytes .../2.3/taskArtifacts/outputFileStates.bin | Bin 0 -> 19022 bytes .gradle/2.3/taskArtifacts/taskArtifacts.bin | Bin 0 -> 38676 bytes .project | 16 + .settings/org.eclipse.jdt.core.prefs | 13 + build.gradle | 22 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 52141 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 ++++++++ gradlew.bat | 90 +++++ src/main/java/nl/jssl/sd/Deserializer.java | 12 + src/main/java/nl/jssl/ss/JSONSerializer.java | 21 + src/main/java/nl/jssl/ss/Serializer.java | 45 +++ .../jssl/ss/SerializerCreationException.java | 10 + .../java/nl/jssl/ss/SerializerFactory.java | 5 + .../nl/jssl/ss/SynthSerializerFactory.java | 377 ++++++++++++++++++ src/test/java/nl/jssl/sd/EmptyTest.java | 12 + src/test/java/nl/jssl/sd/IntegerTest.java | 13 + src/test/java/nl/jssl/sd/StringTest.java | 12 + .../java/nl/jssl/ss/StringPropertyTest.java | 51 +++ .../nl/jssl/ss/collections/ArrayTest.java | 34 ++ .../java/nl/jssl/ss/collections/ListTest.java | 41 ++ .../java/nl/jssl/ss/collections/MapTest.java | 59 +++ .../java/nl/jssl/ss/collections/SetTest.java | 43 ++ src/test/java/nl/jssl/ss/nested/Bean1.java | 48 +++ src/test/java/nl/jssl/ss/nested/Bean2.java | 13 + .../java/nl/jssl/ss/nested/Bean2Child.java | 14 + .../nl/jssl/ss/nested/NestedBeanTest.java | 37 ++ .../java/nl/jssl/ss/performance/Jackson.java | 63 +++ .../nl/jssl/ss/performance/SmartJson.java | 54 +++ .../ss/primitives/BooleanPropertyTest.java | 39 ++ .../jssl/ss/primitives/BytePropertyTest.java | 38 ++ .../jssl/ss/primitives/CharPropertyTest.java | 38 ++ .../ss/primitives/DoublePropertyTest.java | 38 ++ .../jssl/ss/primitives/FloatPropertyTest.java | 38 ++ .../jssl/ss/primitives/IntPropertyTest.java | 39 ++ .../jssl/ss/primitives/LongPropertyTest.java | 38 ++ .../jssl/ss/primitives/NullPropertyTest.java | 33 ++ .../jssl/ss/primitives/ShortPropertyTest.java | 38 ++ 43 files changed, 1635 insertions(+) create mode 100644 .classpath create mode 100644 .gradle/2.3/taskArtifacts/cache.properties create mode 100644 .gradle/2.3/taskArtifacts/cache.properties.lock create mode 100644 .gradle/2.3/taskArtifacts/fileHashes.bin create mode 100644 .gradle/2.3/taskArtifacts/fileSnapshots.bin create mode 100644 .gradle/2.3/taskArtifacts/outputFileStates.bin create mode 100644 .gradle/2.3/taskArtifacts/taskArtifacts.bin create mode 100644 .project create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 src/main/java/nl/jssl/sd/Deserializer.java create mode 100644 src/main/java/nl/jssl/ss/JSONSerializer.java create mode 100644 src/main/java/nl/jssl/ss/Serializer.java create mode 100644 src/main/java/nl/jssl/ss/SerializerCreationException.java create mode 100644 src/main/java/nl/jssl/ss/SerializerFactory.java create mode 100644 src/main/java/nl/jssl/ss/SynthSerializerFactory.java create mode 100644 src/test/java/nl/jssl/sd/EmptyTest.java create mode 100644 src/test/java/nl/jssl/sd/IntegerTest.java create mode 100644 src/test/java/nl/jssl/sd/StringTest.java create mode 100644 src/test/java/nl/jssl/ss/StringPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/collections/ArrayTest.java create mode 100644 src/test/java/nl/jssl/ss/collections/ListTest.java create mode 100644 src/test/java/nl/jssl/ss/collections/MapTest.java create mode 100644 src/test/java/nl/jssl/ss/collections/SetTest.java create mode 100644 src/test/java/nl/jssl/ss/nested/Bean1.java create mode 100644 src/test/java/nl/jssl/ss/nested/Bean2.java create mode 100644 src/test/java/nl/jssl/ss/nested/Bean2Child.java create mode 100644 src/test/java/nl/jssl/ss/nested/NestedBeanTest.java create mode 100644 src/test/java/nl/jssl/ss/performance/Jackson.java create mode 100644 src/test/java/nl/jssl/ss/performance/SmartJson.java create mode 100644 src/test/java/nl/jssl/ss/primitives/BooleanPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/BytePropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/CharPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/DoublePropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/FloatPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/IntPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/LongPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/NullPropertyTest.java create mode 100644 src/test/java/nl/jssl/ss/primitives/ShortPropertyTest.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..e9f40da --- /dev/null +++ b/.classpath @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.gradle/2.3/taskArtifacts/cache.properties b/.gradle/2.3/taskArtifacts/cache.properties new file mode 100644 index 0000000..45fe99b --- /dev/null +++ b/.gradle/2.3/taskArtifacts/cache.properties @@ -0,0 +1 @@ +#Wed Aug 12 16:00:24 CEST 2015 diff --git a/.gradle/2.3/taskArtifacts/cache.properties.lock b/.gradle/2.3/taskArtifacts/cache.properties.lock new file mode 100644 index 0000000000000000000000000000000000000000..d47aea32196944f54c44b7ca5e7a220fd1531b77 GIT binary patch literal 17 VcmZSHX(r{sbzAi=0~j#P1^_2v1JM8g literal 0 HcmV?d00001 diff --git a/.gradle/2.3/taskArtifacts/fileHashes.bin b/.gradle/2.3/taskArtifacts/fileHashes.bin new file mode 100644 index 0000000000000000000000000000000000000000..97cbc2eed92990ab3d71f93497594d593fbe3055 GIT binary patch literal 26245 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 Xn(Ad`Tqo+O2K@kk_{ymeXyN~V_woMN literal 0 HcmV?d00001 diff --git a/.gradle/2.3/taskArtifacts/fileSnapshots.bin b/.gradle/2.3/taskArtifacts/fileSnapshots.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f56db41e4ef907991253762280bb2660d14d7cb GIT binary patch literal 85825 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 literal 0 HcmV?d00001 diff --git a/.project b/.project new file mode 100644 index 0000000..6dc5fad --- /dev/null +++ b/.project @@ -0,0 +1,16 @@ + + + SyntheticSerializer + + + + org.eclipse.jdt.core.javanature + + + + org.eclipse.jdt.core.javabuilder + + + + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ad76736 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +# +#Tue Aug 18 20:35:37 CEST 2015 +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..8002c1e --- /dev/null +++ b/build.gradle @@ -0,0 +1,22 @@ + +apply plugin: 'java' +apply plugin: 'eclipse' + +repositories{ + mavenLocal() + mavenCentral() +} + +dependencies{ + compile 'commons-io:commons-io:1.4' + compile 'org.javassist:javassist:3.20.0-GA' + + compile 'ch.qos.logback:logback-core:0.9.29' + compile 'org.slf4j:slf4j-api:1.6.1' + compile 'ch.qos.logback:logback-classic:0.9.29' + + testCompile 'junit:junit:4.8.2' + testCompile 'org.mockito:mockito-core:1.9.5' + testCompile 'com.fasterxml.jackson.core:jackson-databind:2.6.1' + +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..085a1cdc27db1185342f15a00441734e74fe3735 GIT binary patch literal 52141 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
)Mf(9O=$zt#xQMm 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/nl/jssl/sd/Deserializer.java b/src/main/java/nl/jssl/sd/Deserializer.java new file mode 100644 index 0000000..85c0d62 --- /dev/null +++ b/src/main/java/nl/jssl/sd/Deserializer.java @@ -0,0 +1,12 @@ +package nl.jssl.sd; + +public class Deserializer { + + public static Object deserialize(String json) { + if (json.equals("{}")) { + return null; + } else + return 1; + } + +} diff --git a/src/main/java/nl/jssl/ss/JSONSerializer.java b/src/main/java/nl/jssl/ss/JSONSerializer.java new file mode 100644 index 0000000..b168f3a --- /dev/null +++ b/src/main/java/nl/jssl/ss/JSONSerializer.java @@ -0,0 +1,21 @@ +package nl.jssl.ss; + +import java.util.Formatter; + +public abstract class JSONSerializer { + protected abstract String handle(T object); + + protected Formatter formatter = new Formatter(); + + public String toJSONString(T object) { + if (object == null) { + return ""; + } else if (object instanceof Number || object instanceof Boolean) { + return "" + object.toString(); + } else if (object instanceof CharSequence || object instanceof Character) { + return "\"" + object.toString() + "\""; + } else { + return handle(object); + } + } +} diff --git a/src/main/java/nl/jssl/ss/Serializer.java b/src/main/java/nl/jssl/ss/Serializer.java new file mode 100644 index 0000000..b983e76 --- /dev/null +++ b/src/main/java/nl/jssl/ss/Serializer.java @@ -0,0 +1,45 @@ +package nl.jssl.ss; + +public class Serializer { + private static SerializerFactory instance = new SynthSerializerFactory(); + + public static String toJSONString(boolean b) { + return Boolean.toString(b); + } + + public static String toJSONString(short s) { + return Short.toString(s); + } + + public static String toJSONString(int i) { + return Integer.toString(i); + } + + public static String toJSONString(float f) { + return Float.toString(f); + } + + public static String toJSONString(double d) { + return Double.toString(d); + } + + public static String toJSONString(long l) { + return Long.toString(l); + } + + public static String toJSONString(char c) { + return "\"" + Character.toString(c) + "\""; + } + + @SuppressWarnings("unchecked") + public static String toJSONString(T o) { + if (o == null) { + return "null"; + } + return instance.createSerializer((Class) o.getClass()).toJSONString(o); + } + + public static void setInstance(SerializerFactory instance) { + Serializer.instance = instance; + } +} diff --git a/src/main/java/nl/jssl/ss/SerializerCreationException.java b/src/main/java/nl/jssl/ss/SerializerCreationException.java new file mode 100644 index 0000000..955adaf --- /dev/null +++ b/src/main/java/nl/jssl/ss/SerializerCreationException.java @@ -0,0 +1,10 @@ +package nl.jssl.ss; + +@SuppressWarnings("serial") +public class SerializerCreationException extends RuntimeException { + + public SerializerCreationException(Throwable t) { + super(t); + } + +} diff --git a/src/main/java/nl/jssl/ss/SerializerFactory.java b/src/main/java/nl/jssl/ss/SerializerFactory.java new file mode 100644 index 0000000..49af73c --- /dev/null +++ b/src/main/java/nl/jssl/ss/SerializerFactory.java @@ -0,0 +1,5 @@ +package nl.jssl.ss; + +public interface SerializerFactory { + public JSONSerializer createSerializer(Class beanjavaClass); +} diff --git a/src/main/java/nl/jssl/ss/SynthSerializerFactory.java b/src/main/java/nl/jssl/ss/SynthSerializerFactory.java new file mode 100644 index 0000000..daba6ba --- /dev/null +++ b/src/main/java/nl/jssl/ss/SynthSerializerFactory.java @@ -0,0 +1,377 @@ +package nl.jssl.ss; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; +import javassist.CtNewMethod; +import javassist.Modifier; +import javassist.NotFoundException; + +public class SynthSerializerFactory implements SerializerFactory { + private static final String STRING = "java.lang.String"; + private static final String BOOLEAN = "java.lang.Boolean"; + private static final String CHARACTER = "java.lang.Character"; + private static final String BYTE = "java.lang.Byte"; + private static final String DOUBLE = "java.lang.Double"; + private static final String FLOAT = "java.lang.Float"; + private static final String LONG = "java.lang.Long"; + private static final String SHORT = "java.lang.Short"; + private static final String INTEGER = "java.lang.Integer"; + + private final static Set wrappersAndString = new HashSet(Arrays.asList(BOOLEAN, CHARACTER, BYTE, DOUBLE, FLOAT, LONG, SHORT, INTEGER, + STRING)); + + private static final String COLLECTION = "java.util.Collection"; + private static final String LIST = "java.util.List"; + private static final String SET = "java.util.Set"; + private static final String MAP = "java.util.Map"; + + private static final Map> serializers = new HashMap<>(); + private static final String ROOT_PACKAGE = "serializer."; + + private final ClassPool pool = ClassPool.getDefault(); + private CtClass serializerBase; + private final Map primitiveWrappers = new HashMap(); + + public SynthSerializerFactory() { + init(); + } + + void init() { + try { + serializerBase = pool.get(JSONSerializer.class.getName()); + + primitiveWrappers.put("int", pool.get(INTEGER)); + primitiveWrappers.put("short", pool.get(SHORT)); + primitiveWrappers.put("byte", pool.get(BYTE)); + primitiveWrappers.put("long", pool.get(LONG)); + primitiveWrappers.put("float", pool.get(FLOAT)); + primitiveWrappers.put("double", pool.get(DOUBLE)); + primitiveWrappers.put("boolean", pool.get(BOOLEAN)); + primitiveWrappers.put("char", pool.get(CHARACTER)); + } catch (NotFoundException e) { + throw new SerializerCreationException(e); + } + } + + public JSONSerializer createSerializer(Class beanjavaClass) { + try { + CtClass beanClass = pool.get(beanjavaClass.getName()); + + JSONSerializer jsonSerializer = createSerializer(beanClass); + + return jsonSerializer; + } catch (NotFoundException e) { + throw new SerializerCreationException(e); + } + } + + @SuppressWarnings("unchecked") + private JSONSerializer createSerializer(CtClass beanClass) { + if (serializers.containsKey(createSerializerName(beanClass))) { + return (JSONSerializer) serializers.get(createSerializerName(beanClass)); + } + try { + return tryCreateSerializer(beanClass); + } catch (NotFoundException | CannotCompileException | InstantiationException | IllegalAccessException e) { + throw new SerializerCreationException(e); + } + } + + private JSONSerializer tryCreateSerializer(CtClass beanClass) throws NotFoundException, CannotCompileException, InstantiationException, + IllegalAccessException { + CtClass serializerClass = pool.makeClass(createSerializerName(beanClass), serializerBase); + + addToJsonStringMethod(beanClass, serializerClass); + + JSONSerializer jsonSerializer = createSerializerInstance(serializerClass); + + serializers.put(createSerializerName(beanClass), jsonSerializer); + return jsonSerializer; + } + + /* + * create method source, compile it and add it to the class under construction + */ + private void addToJsonStringMethod(CtClass beanClass, CtClass serializerClass) throws NotFoundException, CannotCompileException { + serializerClass.addMethod(CtNewMethod.make(createToJSONStringMethodSource(beanClass), serializerClass)); + } + + /* + * Creates the source, handling the for JSON different types of classes + */ + private String createToJSONStringMethodSource(CtClass beanClass) throws NotFoundException { + String source = "public String handle(Object object){\n"; + if (beanClass.isArray()) { + source += "\tObject[] array=(Object[])object;\n"; + source += handleArray(beanClass); + } else if (isCollection(beanClass)) { + source += "\tObject[] array=((java.util.Collection)object).toArray();\n"; + source += handleArray(beanClass); + } else if (isMap(beanClass)) { + source += handleMap(beanClass); + } else if (!isPrimitiveOrWrapperOrString(beanClass)) { + List getters = getGetters(beanClass); + if (shouldAddGetterCallers(getters)) { + source = addGetterCallers(beanClass, source, getters); + } + } else { + source += "\treturn \"\";}"; + } + System.out.println(source); + return source; + } + + /* + * Any Collection is converted to an array, after which code is generated to handle the single elements. + * + * A subserializer is created for every single element, but most of the time it will be the same cached instance. + * + * The generated code fills a StringBuilder. The values are generated by the subserializers + */ + private String handleArray(CtClass beanClass) { + String source = "\tStringBuilder result=new StringBuilder(\"[\");\n"; + source += "\tfor (int i=0; i getters) throws NotFoundException { + int index = 0; + source += "\treturn "; + source += "\"{"; + for (CtMethod getter : getters) { + source = addPair(beanClass, source, getter); + if (index++ < getters.size() - 1) { + source += ","; + } + } + source += "}\";\n}"; + return source; + } + + @SuppressWarnings("unchecked") + private JSONSerializer createSerializerInstance(CtClass serializerClass) throws InstantiationException, IllegalAccessException, + CannotCompileException { + return (JSONSerializer) serializerClass.toClass().newInstance(); + } + + /* + * custom root package is prepended to avoid the java.lang class in which it's illegal to create new classes + * + * Array marks ( '[]' ) are replaced by the 'Array', Otherwise the SerializerClassName would be syntactically incorrect + */ + public String createSerializerName(CtClass beanClass) { + return createSerializerName(beanClass.getName()); + } + + public String createSerializerName(String name) { + return ROOT_PACKAGE + name.replaceAll("\\[\\]", "Array") + "Serializer"; + } + + private boolean isCollection(CtClass beanClass) throws NotFoundException { + List interfaces = new ArrayList(Arrays.asList(beanClass.getInterfaces())); + interfaces.add(beanClass); + for (CtClass interfaze : interfaces) { + if (interfaze.getName().equals(COLLECTION) || interfaze.getName().equals(LIST) || interfaze.getName().equals(SET)) { + return true; + } + } + return false; + } + + private boolean isMap(CtClass beanClass) throws NotFoundException { + List interfaces = new ArrayList(Arrays.asList(beanClass.getInterfaces())); + interfaces.add(beanClass); + for (CtClass interfaze : interfaces) { + if (interfaze.getName().equals(MAP)) { + return true; + } + } + return false; + } + + /* + * The JSON vernacular for key:value is pair... + */ + private String addPair(CtClass classToSerialize, String source, CtMethod getter) throws NotFoundException { + source += jsonKey(getter); + source += ": "; // what is the rule when it comes to spaces in json? + source += jsonValue(classToSerialize, getter); + return source; + } + + /* + * derive property key from getter + */ + private String jsonKey(CtMethod getter) { + return "\\\"" + toFieldName(getter.getName()) + "\\\""; + } + + private String jsonValue(CtClass classToSerialize, CtMethod getter) throws NotFoundException { + String source = ""; + CtClass returnType = getter.getReturnType(); + + /* primitives are wrapped so the produced methods adhere to the JSONSerializer interface */ + source = createSubSerializerForReturnTypeAndAddInvocationToSource(classToSerialize, getter, source, returnType); + + return source; + } + + private String createSubSerializerForReturnTypeAndAddInvocationToSource(CtClass classToSerialize, CtMethod getter, String source, CtClass returnType) { + /* NB there does not seem to be auto(un))boxing nor generic types (or other jdk1.5 stuff) in javassist compileable code */ + + source += "\"+" + Serializer.class.getName() + ".toJSONString("; + + // cast because of lack of generics + source += "(" + cast(regularClassname(classToSerialize.getName())) + "object)." + getter.getName() + "()"; + + source += ")+\""; + return source; + } + + /* + * turns for example 'getValue' into 'value' + */ + private String toFieldName(String name) { + return name.substring(3, 4).toLowerCase() + (name.length() > 4 ? name.substring(4) : ""); + } + + public String regularClassname(String name) { + return name.replaceAll("\\$", "."); + } + + private String cast(String classToSerialize) { + return "(" + classToSerialize + ")"; + } + + /* + * Retrieves getter methods from a class + */ + private List getGetters(CtClass beanClass) { + List methods = new ArrayList(); + List fields = getAllFields(beanClass); + for (CtField field : fields) { + try { + CtMethod method = beanClass.getMethod(getGetterMethod(field), getDescription(field)); + if (Modifier.isPublic(method.getModifiers())) { + methods.add(method); + } + } catch (NotFoundException n) { + // ignore + } + } + return methods; + } + + private String getGetterMethod(CtField field) { + return "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1); + } + + private List getAllFields(CtClass beanClass) { + try { + List allfields = new ArrayList<>(); + for (CtField field : beanClass.getDeclaredFields()) { + allfields.add(field); + } + if (beanClass.getSuperclass() != null) { + return getAllFields(beanClass.getSuperclass(), allfields); + } + return allfields; + } catch (NotFoundException e) { + throw new SerializerCreationException(e); + } + + } + + private List getAllFields(CtClass beanClass, List allfields) { + for (CtField field : beanClass.getDeclaredFields()) { + allfields.add(field); + } + + return allfields; + } + + /* + * is getter list is not empty then callers should be added + */ + boolean shouldAddGetterCallers(List getters) { + return !getters.isEmpty(); + } + + String getDescription(CtField field) throws NotFoundException { + if (field.getType().isArray()) { + return "()[" + innerClassName(field.getType().getName()) + ";"; + } else if (!field.getType().isPrimitive()) { + return "()" + innerClassName(field.getType().getName()) + ";"; + } else { + + return "()" + asPrimitive(field.getType().getName()); + } + } + + String asPrimitive(String name) { + switch (name) { + case "int": + return "I"; + case "byte": + return "B"; + case "float": + return "F"; + case "long": + return "J"; + case "boolean": + return "Z"; + case "char": + return "C"; + case "double": + return "D"; + case "short": + return "S"; + } + return ""; + } + + String innerClassName(String name) { + return "L" + name.replaceAll("\\.", "/").replaceAll("\\[\\]", ""); + } + + static boolean isPrimitiveOrWrapperOrString(CtClass beanClass) { + return beanClass.isPrimitive() || wrappersAndString.contains(beanClass.getName()); + } +} diff --git a/src/test/java/nl/jssl/sd/EmptyTest.java b/src/test/java/nl/jssl/sd/EmptyTest.java new file mode 100644 index 0000000..2da0762 --- /dev/null +++ b/src/test/java/nl/jssl/sd/EmptyTest.java @@ -0,0 +1,12 @@ +package nl.jssl.sd; + +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; + +public class EmptyTest { + @Test + public void null_shouldReturnEmpty() { + assertEquals(null, Deserializer.deserialize("{}")); + } +} diff --git a/src/test/java/nl/jssl/sd/IntegerTest.java b/src/test/java/nl/jssl/sd/IntegerTest.java new file mode 100644 index 0000000..42fe1f7 --- /dev/null +++ b/src/test/java/nl/jssl/sd/IntegerTest.java @@ -0,0 +1,13 @@ +package nl.jssl.sd; + +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; + +public class IntegerTest { + + @Test + public void testPrimitive() { + assertEquals(1, Deserializer.deserialize("1")); + } +} diff --git a/src/test/java/nl/jssl/sd/StringTest.java b/src/test/java/nl/jssl/sd/StringTest.java new file mode 100644 index 0000000..3646aa6 --- /dev/null +++ b/src/test/java/nl/jssl/sd/StringTest.java @@ -0,0 +1,12 @@ +package nl.jssl.sd; + +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; + +public class StringTest { + @Test + public void shouldReturnStringvalue() { + assertEquals("test", Deserializer.deserialize("\"test\"")); + } +} diff --git a/src/test/java/nl/jssl/ss/StringPropertyTest.java b/src/test/java/nl/jssl/ss/StringPropertyTest.java new file mode 100644 index 0000000..d484ee2 --- /dev/null +++ b/src/test/java/nl/jssl/ss/StringPropertyTest.java @@ -0,0 +1,51 @@ +package nl.jssl.ss; + +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; + +public class StringPropertyTest { + + @Test + public void stringValue() { + assertEquals("\"value\"", Serializer.toJSONString("value")); + } + + @Test + public void stringProperty() { + Bean object = new Bean(); + object.setData1("value1"); + object.setData2("value2"); + assertEquals("{\"data1\": \"value1\",\"data2\": \"value2\"}", Serializer.toJSONString(object)); + } + + @Test + public void stringPropertyNull() { + Bean object = new Bean(); + object.setData1("value1"); + object.setData2("null"); + assertEquals("{\"data1\": \"value1\",\"data2\": \"null\"}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/collections/ArrayTest.java b/src/test/java/nl/jssl/ss/collections/ArrayTest.java new file mode 100644 index 0000000..3b311ed --- /dev/null +++ b/src/test/java/nl/jssl/ss/collections/ArrayTest.java @@ -0,0 +1,34 @@ +package nl.jssl.ss.collections; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class ArrayTest { + @Test + public void testValue() { + assertEquals("[\"value1\", \"value2\"]", Serializer.toJSONString(new String[] { "value1", "value2" })); + } + + @Test + public void testPropertyValue() { + Bean object = new Bean(); + object.setArray(new String[] { "value1", "value2" }); + assertEquals("{\"array\": [\"value1\", \"value2\"]}", Serializer.toJSONString(object)); + } + + public class Bean { + private String[] array; + + public String[] getArray() { + return array; + } + + public void setArray(String[] array) { + this.array = array; + } + + } + +} diff --git a/src/test/java/nl/jssl/ss/collections/ListTest.java b/src/test/java/nl/jssl/ss/collections/ListTest.java new file mode 100644 index 0000000..7e03552 --- /dev/null +++ b/src/test/java/nl/jssl/ss/collections/ListTest.java @@ -0,0 +1,41 @@ +package nl.jssl.ss.collections; + +import static junit.framework.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class ListTest { + @Test + public void testValue() { + List list = new ArrayList(); + list.add("value1"); + list.add("value2"); + assertEquals("[\"value1\", \"value2\"]", Serializer.toJSONString(list)); + } + + @Test + public void testPropertyValue() { + Bean object = new Bean(); + object.setArray(new String[] { "value1", "value2" }); + assertEquals("{\"array\": [\"value1\", \"value2\"]}", Serializer.toJSONString(object)); + } + + public class Bean { + private String[] array; + + public String[] getArray() { + return array; + } + + public void setArray(String[] array) { + this.array = array; + } + + } + +} diff --git a/src/test/java/nl/jssl/ss/collections/MapTest.java b/src/test/java/nl/jssl/ss/collections/MapTest.java new file mode 100644 index 0000000..be4529b --- /dev/null +++ b/src/test/java/nl/jssl/ss/collections/MapTest.java @@ -0,0 +1,59 @@ +package nl.jssl.ss.collections; + +import static junit.framework.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import nl.jssl.ss.SerializerCreationException; +import nl.jssl.ss.Serializer; +import nl.jssl.ss.SynthSerializerFactory; + +import org.junit.Test; + +public class MapTest { + @Test + public void testValue() { + Map map = new HashMap(); + map.put("key1", "value1"); + map.put("key2", "value2"); + String jsonString = Serializer.toJSONString(map); + assertTrue("{\"key1\": \"value1\", \"key2\": \"value2\"}".equals(jsonString) || "{\"key2\": \"value2\", \"key1\": \"value1\"}".equals(jsonString)); + } + + @Test + public void testPropertyValue() { + Bean object = new Bean(); + Map map = new HashMap(); + map.put("key1", "value1"); + map.put("key2", "value2"); + object.setMap(map); + String jsonString = Serializer.toJSONString(object); + assertTrue("{\"map\": {\"key1\": \"value1\", \"key2\": \"value2\"}}".equals(jsonString) + || "{\"map\": {\"key2\": \"value2\", \"key1\": \"value1\"}}".equals(jsonString)); + } + + @Test + public void pumpUpTheVolume() { + Serializer.setInstance(new SynthSerializerFactory()); + try { + throw new SerializerCreationException(new Exception()); + } catch (Exception e) { + } + } + + public class Bean { + + private Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + } + +} diff --git a/src/test/java/nl/jssl/ss/collections/SetTest.java b/src/test/java/nl/jssl/ss/collections/SetTest.java new file mode 100644 index 0000000..b077c97 --- /dev/null +++ b/src/test/java/nl/jssl/ss/collections/SetTest.java @@ -0,0 +1,43 @@ +package nl.jssl.ss.collections; + +import static junit.framework.Assert.assertTrue; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class SetTest { + @Test + public void testValue() { + Set list = new HashSet(); + list.add("value1"); + list.add("value2"); + String jsonString = Serializer.toJSONString(list); + assertTrue("[\"value2\", \"value1\"]".equals(jsonString) || "[\"value1\", \"value2\"]".equals(jsonString)); + } + + @Test + public void testPropertyValue() { + Bean object = new Bean(); + object.setSet(new HashSet(Arrays.asList("value1", "value2"))); + String jsonString = Serializer.toJSONString(object); + assertTrue("{\"set\": [\"value2\", \"value1\"]}".equals(jsonString) || "{\"set\": [\"value1\", \"value2\"]}".equals(jsonString)); + } + + public 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/jssl/ss/nested/Bean1.java b/src/test/java/nl/jssl/ss/nested/Bean1.java new file mode 100644 index 0000000..68bdd81 --- /dev/null +++ b/src/test/java/nl/jssl/ss/nested/Bean1.java @@ -0,0 +1,48 @@ +package nl.jssl.ss.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; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((data1 == null) ? 0 : data1.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Bean1 other = (Bean1) obj; + if (data1 == null) { + if (other.data1 != null) + return false; + } else if (!data1.equals(other.data1)) + return false; + return true; + } + +} diff --git a/src/test/java/nl/jssl/ss/nested/Bean2.java b/src/test/java/nl/jssl/ss/nested/Bean2.java new file mode 100644 index 0000000..53594d6 --- /dev/null +++ b/src/test/java/nl/jssl/ss/nested/Bean2.java @@ -0,0 +1,13 @@ +package nl.jssl.ss.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/jssl/ss/nested/Bean2Child.java b/src/test/java/nl/jssl/ss/nested/Bean2Child.java new file mode 100644 index 0000000..8071d75 --- /dev/null +++ b/src/test/java/nl/jssl/ss/nested/Bean2Child.java @@ -0,0 +1,14 @@ +package nl.jssl.ss.nested; + +public class Bean2Child extends Bean2 { + private String data3; + + public String getData3() { + return data3; + } + + public void setData3(String data3) { + this.data3 = data3; + } + +} diff --git a/src/test/java/nl/jssl/ss/nested/NestedBeanTest.java b/src/test/java/nl/jssl/ss/nested/NestedBeanTest.java new file mode 100644 index 0000000..780ab39 --- /dev/null +++ b/src/test/java/nl/jssl/ss/nested/NestedBeanTest.java @@ -0,0 +1,37 @@ +package nl.jssl.ss.nested; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class NestedBeanTest { + @Test + public void testBeans() { + Bean1 object1 = new Bean1(); + object1.setData1("value1"); + Bean2 object2 = new Bean2(); + object2.setData2("value2"); + object1.setBean2(object2); + assertEquals("{\"data1\": \"value1\",\"bean2\": {\"data2\": \"value2\"}}", Serializer.toJSONString(object1)); + assertEquals("{\"data1\": \"value1\",\"bean2\": {\"data2\": \"value2\"}}", Serializer.toJSONString(object1)); + } + + @Test + public void testNullValueForBean() { + Bean1 object1 = new Bean1(); + object1.setData1("value1"); + assertEquals("{\"data1\": \"value1\",\"bean2\": null}", Serializer.toJSONString(object1)); + } + + @Test + public void testBeanChildren() { + Bean1 object1 = new Bean1(); + object1.setData1("value1"); + Bean2Child object3 = new Bean2Child(); + object3.setData2("value2"); + object3.setData3("value3"); + object1.setBean2(object3); + assertEquals("{\"data1\": \"value1\",\"bean2\": {\"data3\": \"value3\",\"data2\": \"value2\"}}", Serializer.toJSONString(object1)); + } +} diff --git a/src/test/java/nl/jssl/ss/performance/Jackson.java b/src/test/java/nl/jssl/ss/performance/Jackson.java new file mode 100644 index 0000000..85f3cde --- /dev/null +++ b/src/test/java/nl/jssl/ss/performance/Jackson.java @@ -0,0 +1,63 @@ +package nl.jssl.ss.performance; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import nl.jssl.ss.Serializer; +import nl.jssl.ss.nested.Bean1; +import nl.jssl.ss.nested.Bean2; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class Jackson { + List trashbin = new ArrayList(); + + @Test + public void jackson() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + Bean1 bean1 = new Bean1(); + Bean2 bean2 = new Bean2(); + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + String valueAsString = objectMapper.writeValueAsString(bean1); + String jsonString = Serializer.toJSONString(bean1); + + for (int c = 0; c < 20; c++) { + trashbin.clear(); + System.gc(); + long t0 = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + bean1 = new Bean1(); + bean2 = new Bean2(); + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + valueAsString = objectMapper.writeValueAsString(bean1); + // System.out.println(valueAsString); + trashbin.add(valueAsString); + } + System.out.print(System.currentTimeMillis() - t0); + System.out.print(","); + trashbin.clear(); + System.gc(); + long tt0 = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + bean1 = new Bean1(); + bean2 = new Bean2(); + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + jsonString = Serializer.toJSONString(bean1); + // System.out.println(jsonString); + trashbin.add(jsonString); + } + System.out.println(System.currentTimeMillis() - tt0); + } + + } +} diff --git a/src/test/java/nl/jssl/ss/performance/SmartJson.java b/src/test/java/nl/jssl/ss/performance/SmartJson.java new file mode 100644 index 0000000..9550890 --- /dev/null +++ b/src/test/java/nl/jssl/ss/performance/SmartJson.java @@ -0,0 +1,54 @@ +package nl.jssl.ss.performance; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import net.minidev.json.JSONValue; +import nl.jssl.ss.Serializer; +import nl.jssl.ss.nested.Bean1; +import nl.jssl.ss.nested.Bean2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SmartJson { + public void jackson() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + Bean1 bean1 = new Bean1(); + Bean2 bean2 = new Bean2(); + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + + Serializer.toJSONString(bean1); + JSONValue.toJSONString(bean1); + for (int c = 0; c < 200; c++) { + System.gc(); + long t0 = System.currentTimeMillis(); + List trashbin = new ArrayList(); + for (int i = 0; i < 10000; i++) { + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + String valueAsString = JSONValue.toJSONString(bean1); + trashbin.add(valueAsString); + } + System.out.print(System.currentTimeMillis() - t0); + System.out.print(","); + trashbin.clear(); + System.gc(); + long tt0 = System.currentTimeMillis(); + for (int i = 0; i < 10000; i++) { + bean1.setData1(UUID.randomUUID().toString()); + bean1.setBean2(bean2); + bean2.setData2(UUID.randomUUID().toString()); + String jsonString = Serializer.toJSONString(bean1); + // System.out.println(jsonString); + trashbin.add(jsonString); + } + System.out.println(System.currentTimeMillis() - tt0); + } + + } +} diff --git a/src/test/java/nl/jssl/ss/primitives/BooleanPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/BooleanPropertyTest.java new file mode 100644 index 0000000..03921b7 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/BooleanPropertyTest.java @@ -0,0 +1,39 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class BooleanPropertyTest { + + @Test + public void testPrimitive() { + assertEquals("false", Serializer.toJSONString(false)); + } + + @Test + public void testWrapper() { + assertEquals("false", Serializer.toJSONString(Boolean.FALSE)); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData(true); + assertEquals("{\"data\": true}", Serializer.toJSONString(object)); + } + + public class Bean { + private boolean data; + + public boolean getData() { + return data; + } + + public void setData(boolean data) { + this.data = data; + } + + } +} diff --git a/src/test/java/nl/jssl/ss/primitives/BytePropertyTest.java b/src/test/java/nl/jssl/ss/primitives/BytePropertyTest.java new file mode 100644 index 0000000..adcf854 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/BytePropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class BytePropertyTest { + @Test + public void testPrimitive() { + assertEquals("-55", Serializer.toJSONString((byte) -55)); + } + + @Test + public void testWrapper() { + assertEquals("55", Serializer.toJSONString((byte) 55)); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData((byte) 1); + assertEquals("{\"data\": 1}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/primitives/CharPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/CharPropertyTest.java new file mode 100644 index 0000000..6598f82 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/CharPropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class CharPropertyTest { + @Test + public void testPrimitive() { + assertEquals("\"d\"", Serializer.toJSONString('d')); + } + + @Test + public void testWrapper() { + assertEquals("\"s\"", Serializer.toJSONString('s')); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData('a'); + assertEquals("{\"data\": \"a\"}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/primitives/DoublePropertyTest.java b/src/test/java/nl/jssl/ss/primitives/DoublePropertyTest.java new file mode 100644 index 0000000..629eb6d --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/DoublePropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class DoublePropertyTest { + @Test + public void testPrimitive() { + assertEquals("-55.6", Serializer.toJSONString(-55.6D)); + } + + @Test + public void testWrapper() { + assertEquals("55.0", Serializer.toJSONString(Double.valueOf("55.0"))); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData(326.2D); + assertEquals("{\"data\": 326.2}", Serializer.toJSONString(object)); + } + + public class Bean { + private double data; + + public double getData() { + return data; + } + + public void setData(double data) { + this.data = data; + } + + } +} diff --git a/src/test/java/nl/jssl/ss/primitives/FloatPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/FloatPropertyTest.java new file mode 100644 index 0000000..e870589 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/FloatPropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class FloatPropertyTest { + @Test + public void testPrimitive() { + assertEquals("-55.6", Serializer.toJSONString(-55.6F)); + } + + @Test + public void testWrapper() { + assertEquals("55.0", Serializer.toJSONString(Float.valueOf("55.0"))); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData(1F); + assertEquals("{\"data\": 1.0}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/primitives/IntPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/IntPropertyTest.java new file mode 100644 index 0000000..c0485c0 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/IntPropertyTest.java @@ -0,0 +1,39 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class IntPropertyTest { + + @Test + public void testPrimitive() { + assertEquals("-55", Serializer.toJSONString(-55)); + } + + @Test + public void testWrapper() { + assertEquals("55", Serializer.toJSONString(Integer.valueOf("55"))); + } + + @Test + public void testPropertyValue() { + Bean object = new Bean(); + object.setData(1); + assertEquals("{\"data\": 1}", Serializer.toJSONString(object)); + } + + public class Bean { + private int data; + + public int getData() { + return data; + } + + public void setData(int data) { + this.data = data; + } + + } +} diff --git a/src/test/java/nl/jssl/ss/primitives/LongPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/LongPropertyTest.java new file mode 100644 index 0000000..3f1ddc1 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/LongPropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class LongPropertyTest { + @Test + public void testPrimitive() { + assertEquals("-55", Serializer.toJSONString(-55L)); + } + + @Test + public void testWrapper() { + assertEquals("55", Serializer.toJSONString(Long.valueOf("55"))); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData(1L); + assertEquals("{\"data\": 1}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/primitives/NullPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/NullPropertyTest.java new file mode 100644 index 0000000..f5a04ad --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/NullPropertyTest.java @@ -0,0 +1,33 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class NullPropertyTest { + + @Test + public void testPrimitive() { + assertEquals("null", Serializer.toJSONString(null)); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + assertEquals("{\"data\": null}", Serializer.toJSONString(object)); + } + + public 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/jssl/ss/primitives/ShortPropertyTest.java b/src/test/java/nl/jssl/ss/primitives/ShortPropertyTest.java new file mode 100644 index 0000000..f87d022 --- /dev/null +++ b/src/test/java/nl/jssl/ss/primitives/ShortPropertyTest.java @@ -0,0 +1,38 @@ +package nl.jssl.ss.primitives; + +import static junit.framework.Assert.assertEquals; +import nl.jssl.ss.Serializer; + +import org.junit.Test; + +public class ShortPropertyTest { + @Test + public void testPrimitive() { + assertEquals("-55", Serializer.toJSONString((short) -55)); + } + + @Test + public void testWrapper() { + assertEquals("5", Serializer.toJSONString(Short.valueOf("5"))); + } + + @Test + public void testProperty() { + Bean object = new Bean(); + object.setData((short) 3); + assertEquals("{\"data\": 3}", Serializer.toJSONString(object)); + } + + public class Bean { + private short data; + + public short getData() { + return data; + } + + public void setData(short data) { + this.data = data; + } + + } +}