json-serialiser

fixed nullpointer of nested serialisations by creating an

11/26/2018 5:01:11 PM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/JSONSerialiser.java b/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/JSONSerialiser.java
index 4672c98..cd5fcb8 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/JSONSerialiser.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/JSONSerialiser.java
@@ -24,36 +24,17 @@ import java.util.Map;
  */
 public class JSONSerialiser {
 
-    private static final Collection<Object> VISITED = new ArrayList<>();
-    private static Writer WRITER;
-
-    private static class StringBuilderWriter extends Writer {
-
-        private final StringBuilder stringBuilder;
-
-        public StringBuilderWriter(StringBuilder stringBuilder) {
-            this.stringBuilder = stringBuilder;
-        }
-
-        @Override
-        public void write(char[] cbuf, int off, int len) {
-            stringBuilder.append(cbuf, off, len);
-        }
-
-        @Override
-        public void flush() {
-        }
-
-        @Override
-        public void close() {
-        }
+    private final Collection<Object> visited;
+    private final Writer writer;
 
+    private JSONSerialiser(Writer writer) {
+        this.visited = new ArrayList<>();
+        this.writer = writer;
     }
 
     public static void serialise(Object bean, Writer writer, boolean cyclicFields) throws IOException {
-        JSONSerialiser.WRITER = writer;
-        serialiseBean(bean, cyclicFields);
-        JSONSerialiser.WRITER = null;
+        JSONSerialiser jsonSerialiser = new JSONSerialiser(writer);
+        jsonSerialiser.serialiseBean(bean, cyclicFields);
     }
 
     public static void serialise(Object bean, Writer writer) throws IOException {
@@ -74,38 +55,30 @@ public class JSONSerialiser {
     }
 
     public static String serialiseCylicObject(Object bean) {
-        resetCycleBreaker();
-        String serialise = serialise(bean);
-        resetCycleBreaker();
-        return serialise;
+        return serialise(bean);
     }
 
     public static String serialiseAcylicObject(Object bean) {
-        resetCycleBreaker();
-        String serialise = serialise(bean, false);
-        resetCycleBreaker();
-        return serialise;
+        return serialise(bean, false);
     }
 
     public static void serialiseAcylicObject(Object bean, Writer writer) throws IOException {
-        resetCycleBreaker();
         serialise(bean, writer, false);
-        resetCycleBreaker();
     }
 
-    public static void resetCycleBreaker() {
-        JSONSerialiser.VISITED.clear();
+    private void resetCycleBreaker() {
+        this.visited.clear();
     }
 
-    private static void serialiseBean(Object bean, boolean cyclicFields) throws IOException {
+    private void serialiseBean(Object bean, boolean cyclicFields) throws IOException {
         if (bean == null) {
-            JSONSerialiser.WRITER.append("null");
+            this.writer.append("null");
             return;
         }
         Class<?> klass = bean.getClass();
         List<Field> fields = new ArrayList<>();
         fields = getAllFields(fields, klass);
-        JSONSerialiser.WRITER.append("{");
+        this.writer.append("{");
         for (Iterator<Field> it = fields.iterator(); it.hasNext();) {
             Field field = it.next();
             try {
@@ -117,25 +90,25 @@ public class JSONSerialiser {
                 if (!cyclicFields) {
                     resetCycleBreaker();
                 }
-                JSONSerialiser.WRITER.append("\"").append(field.getName()).append("\"");
-                JSONSerialiser.WRITER.append(":");
+                this.writer.append("\"").append(field.getName()).append("\"");
+                this.writer.append(":");
                 wrap(result);
             } catch (Exception ignore) {
                 System.err.println("[JSONSerialiser] field exception: " + ignore);
-                JSONSerialiser.WRITER.append("\"").append("JSON-FIELD-EXCEPTION").append("\"");
+                this.writer.append("\"").append("JSON-FIELD-EXCEPTION").append("\"");
             }
             if (it.hasNext()) {
-                JSONSerialiser.WRITER.append(",");
+                this.writer.append(",");
             }
         }
-        JSONSerialiser.WRITER.append("}");
+        this.writer.append("}");
     }
 
-    private static void serialiseBean(Object bean) throws IOException {
+    private void serialiseBean(Object bean) throws IOException {
         serialiseBean(bean, true);
     }
 
-    private static List<Field> getAllFields(List<Field> fields, Class<?> type) {
+    private List<Field> getAllFields(List<Field> fields, Class<?> type) {
         for (Field field : type.getDeclaredFields()) {
             if (!field.getName().startsWith("ajc$tjp_")) {
                 fields.add(field);
@@ -147,14 +120,14 @@ public class JSONSerialiser {
         return fields;
     }
 
-    private static void wrap(Object object) throws IOException {
+    private void wrap(Object object) throws IOException {
         try {
             if (object == null) {
-                JSONSerialiser.WRITER.append("null");
+                this.writer.append("null");
                 return;
             }
             if (object instanceof Boolean) {
-                JSONSerialiser.WRITER.append("\"").append(String.valueOf(object)).append("\"");
+                this.writer.append("\"").append(String.valueOf(object)).append("\"");
                 return;
             }
             if (object instanceof Character) {
@@ -194,97 +167,97 @@ public class JSONSerialiser {
                 serialiseNumber(date.getTime());
                 return;
             }
-            if (VISITED.stream().anyMatch((visited) -> (visited == object))) {
+            if (visited.stream().anyMatch((visited) -> (visited == object))) {
                 try {
-                    JSONSerialiser.WRITER.append("\"").append(String.valueOf(object)).append("\"");
+                    this.writer.append("\"").append(String.valueOf(object)).append("\"");
                 } catch (Exception e) {
-                    JSONSerialiser.WRITER.append("\"").append(object.getClass().getName()).append("\"");
+                    this.writer.append("\"").append(object.getClass().getName()).append("\"");
                 } finally {
                     return;
                 }
             }
-            VISITED.add(object);
+            visited.add(object);
             serialiseBean(object);
         } catch (ConcurrentModificationException exception) {
             System.err.println("[JSONSerialiser] ConcurrentModificationException");
         } catch (Exception exception) {
             System.err.println("[JSONSerialiser] wrap exception: " + exception);
             exception.printStackTrace();
-            JSONSerialiser.WRITER.append("\"").append("JSON_SERIALISE_EXCEPTION").append("\"");
+            this.writer.append("\"").append("JSON_SERIALISE_EXCEPTION").append("\"");
         }
     }
 
-    private static void serialiseMap(Map map) throws IOException {
+    private void serialiseMap(Map map) throws IOException {
         try {
-            JSONSerialiser.WRITER.append("{");
+            this.writer.append("{");
             for (Iterator<?> it = map.keySet().iterator(); it.hasNext();) {
                 Object key = it.next();
                 if (key == null || map.get(key) == null) {
                     continue;
                 }
                 if (!(key instanceof String)) {
-                    JSONSerialiser.WRITER.append("\"");
+                    this.writer.append("\"");
                     wrap(key);
-                    JSONSerialiser.WRITER.append("\"");
+                    this.writer.append("\"");
                 } else {
                     wrap(key);
                 }
-                JSONSerialiser.WRITER.append(":");
+                this.writer.append(":");
                 wrap(map.get(key));
                 if (it.hasNext()) {
-                    JSONSerialiser.WRITER.append(",");
+                    this.writer.append(",");
                 }
             }
         } catch (Exception ex) {
             System.err.println("[JSONSerialiser] map serialise exception: " + ex);
         } finally {
-            JSONSerialiser.WRITER.append("}");
+            this.writer.append("}");
         }
     }
 
-    private static void serialiseArray(Object array) throws IOException {
-        JSONSerialiser.WRITER.append("[");
+    private void serialiseArray(Object array) throws IOException {
+        this.writer.append("[");
         try {
             int length = Array.getLength(array);
             for (int i = 0; i < length;) {
                 Object object = Array.get(array, i);
                 wrap(object);
                 if (++i < length) {
-                    JSONSerialiser.WRITER.append(",");
+                    this.writer.append(",");
                 }
             }
         } catch (Exception ex) {
             System.err.println("[JSONSerialiser] array serialise exception: " + ex);
         } finally {
-            JSONSerialiser.WRITER.append("]");
+            this.writer.append("]");
         }
     }
 
-    private static void serialiseCollection(Collection collection) throws IOException {
+    private void serialiseCollection(Collection collection) throws IOException {
         try {
-            JSONSerialiser.WRITER.append("[");
+            this.writer.append("[");
             Iterator it = collection.iterator();
             while (it.hasNext()) {
                 Object object = it.next();
                 wrap(object);
                 if (it.hasNext()) {
-                    JSONSerialiser.WRITER.append(",");
+                    this.writer.append(",");
                 }
             }
         } catch (Exception ex) {
             System.err.println("[JSONSerialiser] collection serialise exception: " + ex);
         } finally {
-            JSONSerialiser.WRITER.append("]");
+            this.writer.append("]");
         }
     }
 
-    private static void serialiseString(String string) throws IOException {
+    private void serialiseString(String string) throws IOException {
         if (string == null || string.isEmpty()) {
-            JSONSerialiser.WRITER.append("\"\"");
+            this.writer.append("\"\"");
             return;
         }
         try {
-            JSONSerialiser.WRITER.append('"');
+            this.writer.append('"');
 
             char b;
             char c = 0;
@@ -298,50 +271,50 @@ public class JSONSerialiser {
                 switch (c) {
                     case '\\':
                     case '"':
-                        JSONSerialiser.WRITER.append('\\');
-                        JSONSerialiser.WRITER.append(c);
+                        this.writer.append('\\');
+                        this.writer.append(c);
                         break;
                     case '/':
                         if (b == '<') {
-                            JSONSerialiser.WRITER.append('\\');
+                            this.writer.append('\\');
                         }
-                        JSONSerialiser.WRITER.append(c);
+                        this.writer.append(c);
                         break;
                     case '\b':
-                        JSONSerialiser.WRITER.append("\\b");
+                        this.writer.append("\\b");
                         break;
                     case '\t':
-                        JSONSerialiser.WRITER.append("\\t");
+                        this.writer.append("\\t");
                         break;
                     case '\n':
-                        JSONSerialiser.WRITER.append("\\n");
+                        this.writer.append("\\n");
                         break;
                     case '\f':
-                        JSONSerialiser.WRITER.append("\\f");
+                        this.writer.append("\\f");
                         break;
                     case '\r':
-                        JSONSerialiser.WRITER.append("\\r");
+                        this.writer.append("\\r");
                         break;
                     default:
                         if (c < ' ' || (c >= '\u0080' && c < '\u00a0')
                                 || (c >= '\u2000' && c < '\u2100')) {
-                            JSONSerialiser.WRITER.append("\\u");
+                            this.writer.append("\\u");
                             hexadecimal = Integer.toHexString(c);
-                            JSONSerialiser.WRITER.append("0000", 0, 4 - hexadecimal.length());
-                            JSONSerialiser.WRITER.append(hexadecimal);
+                            this.writer.append("0000", 0, 4 - hexadecimal.length());
+                            this.writer.append(hexadecimal);
                         } else {
-                            JSONSerialiser.WRITER.append(c);
+                            this.writer.append(c);
                         }
                 }
             }
         } catch (Exception ex) {
             System.err.println("[JSONSerialiser] string serialise exception: " + ex);
         } finally {
-            JSONSerialiser.WRITER.append('"');
+            this.writer.append('"');
         }
     }
 
-    private static void serialiseNumber(Number number) throws IOException {
+    private void serialiseNumber(Number number) throws IOException {
         // not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
         final String numberAsString = numberToString(number);
         try {
@@ -349,7 +322,7 @@ public class JSONSerialiser {
             @SuppressWarnings("unused")
             BigDecimal unused = new BigDecimal(numberAsString);
             // Close enough to a JSON number that we will return it unquoted
-            JSONSerialiser.WRITER.append(numberAsString);
+            this.writer.append(numberAsString);
         } catch (NumberFormatException ex) {
             // The Number value is not a valid JSON number.
             // Instead we will quote it as a string
@@ -358,7 +331,7 @@ public class JSONSerialiser {
 
     }
 
-    private static String numberToString(Number number) {
+    private String numberToString(Number number) {
         if (number instanceof Double) {
             if (((Double) number).isInfinite() || ((Double) number).isNaN()) {
                 return String.valueOf(number);
diff --git a/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/StringBuilderWriter.java b/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/StringBuilderWriter.java
new file mode 100644
index 0000000..b76a1e3
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/jsonserialiser/StringBuilderWriter.java
@@ -0,0 +1,35 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.jsonserialiser;
+
+import java.io.Writer;
+
+/**
+ *
+ * @author romulo
+ */
+public class StringBuilderWriter extends Writer {
+
+    private final StringBuilder stringBuilder;
+
+    public StringBuilderWriter(StringBuilder stringBuilder) {
+        this.stringBuilder = stringBuilder;
+    }
+
+    @Override
+    public void write(char[] cbuf, int off, int len) {
+        stringBuilder.append(cbuf, off, len);
+    }
+
+    @Override
+    public void flush() {
+    }
+
+    @Override
+    public void close() {
+    }
+
+}