diff --git a/JsonGeneratorTests/JsonArray.h b/JsonGeneratorTests/JsonArray.h
index 96d7aaa6..f3bc4564 100644
--- a/JsonGeneratorTests/JsonArray.h
+++ b/JsonGeneratorTests/JsonArray.h
@@ -37,9 +37,10 @@ private:
     JsonValue items[N];
     int itemCount;
 
-    virtual void writeTo(StringBuilder& sb)
+    virtual void writeTo(JsonSink& sb)
     {
         sb.append("[");
+        sb.reserveRoom(1);
 
         for (int i = 0; i < itemCount; i++)
         {
@@ -47,6 +48,7 @@ private:
             items[i].writeTo(sb);
         }
 
+        sb.releaseRoom(1);
         sb.append("]");
     }
 };
diff --git a/JsonGeneratorTests/JsonGeneratorTests.vcxproj b/JsonGeneratorTests/JsonGeneratorTests.vcxproj
index 18e185bf..d50f2a04 100644
--- a/JsonGeneratorTests/JsonGeneratorTests.vcxproj
+++ b/JsonGeneratorTests/JsonGeneratorTests.vcxproj
@@ -86,13 +86,13 @@
     
     
     
-    
-    
+    
   
   
     
     
     
+    
     
     
   
diff --git a/JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters b/JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters
index b6aff73e..4a87129b 100644
--- a/JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters
+++ b/JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters
@@ -21,23 +21,17 @@
     
       Source Files
     
-    
-      Source Files
-    
-    
-      Source Files
-    
     
       Source Files
     
     
       Source Files
     
+    
+      Source Files
+    
   
   
-    
-      Header Files
-    
     
       Header Files
     
@@ -50,5 +44,11 @@
     
       Header Files
     
+    
+      Header Files
+    
+    
+      Header Files
+    
   
 
\ No newline at end of file
diff --git a/JsonGeneratorTests/JsonHashTable.h b/JsonGeneratorTests/JsonHashTable.h
index 878915ed..f5a58393 100644
--- a/JsonGeneratorTests/JsonHashTable.h
+++ b/JsonGeneratorTests/JsonHashTable.h
@@ -45,19 +45,24 @@ private:
     KeyValuePair items[N];
     int itemCount;
 
-    virtual void writeTo(StringBuilder& sb)
+    virtual void writeTo(JsonSink& sink)
     {
-        sb.append("{");
+        sink.append("{");
+        sink.reserveRoom(1);
 
         for (int i = 0; i < itemCount; i++)
         {
-            if (i>0) sb.append(",");
-            sb.appendEscaped(items[i].key);
-            sb.append(":");
-            items[i].value.writeTo(sb);
+            if (i>0) sink.append(",");
+
+            JsonValue key(items[i].key);
+
+            key.writeTo(sink);
+            sink.append(":");
+            items[i].value.writeTo(sink);
         }
 
-        sb.append("}");
+        sink.releaseRoom(1);
+        sink.append("}");
     }
 };
 
diff --git a/JsonGeneratorTests/JsonObjectBase.h b/JsonGeneratorTests/JsonObjectBase.h
index c9939250..fe9ee4e0 100644
--- a/JsonGeneratorTests/JsonObjectBase.h
+++ b/JsonGeneratorTests/JsonObjectBase.h
@@ -6,6 +6,7 @@
 #pragma once
 
 #include "JsonValue.h"
+#include "JsonSink.h"
 
 class JsonObjectBase
 {
@@ -17,6 +18,6 @@ public:
         writeTo(sb);
     }
 
-    virtual void writeTo(StringBuilder& sb) = 0;
+    virtual void writeTo(JsonSink& sb) = 0;
 };
 
diff --git a/JsonGeneratorTests/JsonSink.h b/JsonGeneratorTests/JsonSink.h
new file mode 100644
index 00000000..cd8344ac
--- /dev/null
+++ b/JsonGeneratorTests/JsonSink.h
@@ -0,0 +1,19 @@
+/*
+ * Arduino JSON library
+ * Benoit Blanchon 2014 - MIT License
+ */
+
+#pragma once
+
+class JsonSink
+{
+public:
+
+    virtual void append(char c) = 0;
+    virtual void append(const char* s) = 0;
+
+    virtual bool hasRoomFor(int n) = 0;
+    virtual void reserveRoom(int n) = 0;
+    virtual void releaseRoom(int n) = 0;
+};
+
diff --git a/JsonGeneratorTests/JsonValue.cpp b/JsonGeneratorTests/JsonValue.cpp
index 032c28be..26bc42f0 100644
--- a/JsonGeneratorTests/JsonValue.cpp
+++ b/JsonGeneratorTests/JsonValue.cpp
@@ -5,26 +5,88 @@
 
 #include "JsonValue.h"
 #include "JsonObjectBase.h"
+#include 
+#include 
 
-void JsonValue::writeBooleanTo(StringBuilder& sb)
+void JsonValue::writeBooleanTo(JsonSink& sb)
 {
     sb.append(content.boolean ? "true" : "false");
 }
 
-void JsonValue::writeNumberTo(StringBuilder& sb)
+void JsonValue::writeNumberTo(JsonSink& sb)
 {
-    sb.append(content.number);
+    char tmp[16];
+
+    _snprintf(tmp, sizeof(tmp), "%lg", content.number);
+
+    sb.append(tmp);
 }
 
-void JsonValue::writeObjectTo(StringBuilder& sb)
+void JsonValue::writeObjectTo(JsonSink& sink)
 {
     if (content.object)
-        ((JsonObjectBase*) content.object)->writeTo(sb);
+        ((JsonObjectBase*) content.object)->writeTo(sink);
     else
-        sb.append("null");
+        sink.append("null");
 }
 
-void JsonValue::writeStringTo(StringBuilder& sb)
+void JsonValue::writeStringTo(JsonSink& sink)
 {
-    sb.appendEscaped(content.string);
+    auto s = content.string;
+
+    if (!s)
+    {
+        return sink.append("null");
+    }
+
+    if (!sink.hasRoomFor(2))
+    {
+        return;
+    }
+
+    sink.append('\"');
+    sink.reserveRoom(1);
+
+    while (*s)
+    {
+        switch (*s)
+        {
+        case '"':
+            sink.append("\\\"");
+            break;
+
+        case '\\':
+            sink.append("\\\\");
+            break;
+
+        case '\b':
+            sink.append("\\b");
+            break;
+
+        case '\f':
+            sink.append("\\f");
+            break;
+
+        case '\n':
+            sink.append("\\n");
+            break;
+
+        case '\r':
+            sink.append("\\r");
+            break;
+
+        case '\t':
+            sink.append("\\t");
+            break;
+
+        default:
+            sink.append(*s);
+            break;
+        }
+
+        s++;
+    }
+
+    sink.releaseRoom(1);
+    sink.append('\"');
 }
\ No newline at end of file
diff --git a/JsonGeneratorTests/JsonValue.h b/JsonGeneratorTests/JsonValue.h
index 3f9d8f0b..1cf1ee6d 100644
--- a/JsonGeneratorTests/JsonValue.h
+++ b/JsonGeneratorTests/JsonValue.h
@@ -41,10 +41,10 @@ public:
         content.object = &value;
     }
 
-    void writeTo(StringBuilder& sb)
+    void writeTo(JsonSink& sink)
     {
         // handmade polymorphism
-       (this->*implementation)(sb);
+        (this->*implementation)(sink);
     }
     
 private:
@@ -59,10 +59,10 @@ private:
 
     Content content;
 
-    void (JsonValue::*implementation)(StringBuilder& sb);
+    void (JsonValue::*implementation)(JsonSink& sb);
 
-    void writeBooleanTo(StringBuilder& sb);
-    void writeNumberTo(StringBuilder& sb);
-    void writeObjectTo(StringBuilder& sb);
-    void writeStringTo(StringBuilder& sb);
+    void writeBooleanTo(JsonSink& sb);
+    void writeNumberTo(JsonSink& sb);
+    void writeObjectTo(JsonSink& sb);
+    void writeStringTo(JsonSink& sb);
 };
\ No newline at end of file
diff --git a/JsonGeneratorTests/StringBuilderAppendEscapedTests.cpp b/JsonGeneratorTests/JsonValueTests.cpp
similarity index 78%
rename from JsonGeneratorTests/StringBuilderAppendEscapedTests.cpp
rename to JsonGeneratorTests/JsonValueTests.cpp
index 96e07581..ecc0a2b3 100644
--- a/JsonGeneratorTests/StringBuilderAppendEscapedTests.cpp
+++ b/JsonGeneratorTests/JsonValueTests.cpp
@@ -1,11 +1,12 @@
 #include "CppUnitTest.h"
 #include "StringBuilder.h"
+#include "JsonValue.h"
 
 using namespace Microsoft::VisualStudio::CppUnitTestFramework;
 
 namespace JsonGeneratorTests
 {
-    TEST_CLASS(StringBuilderAppendEscapedTests)
+    TEST_CLASS(JsonValueTests)
     {
         char buffer[20];
         StringBuilder* sb;
@@ -16,24 +17,24 @@ namespace JsonGeneratorTests
         {
             sb = new StringBuilder(buffer, sizeof(buffer));
         }
-        
+                
         TEST_METHOD(InitialState)
         {
             assertResultIs("");
         }
 
+        TEST_METHOD(Null)
+        {
+            append((char*)0);
+            assertResultIs("null");
+        }
+
         TEST_METHOD(EmptyString)
         {
             append("");
             assertResultIs("\"\"");
         }
 
-        TEST_METHOD(Null)
-        {
-            append(NULL);
-            assertResultIs("null");
-        }
-
         TEST_METHOD(OneString)
         {
             append("ABCD");
@@ -55,16 +56,23 @@ namespace JsonGeneratorTests
             append("");
             assertResultIs("\"ABCDEFGHIJKLMNOPQ\"");
         }
-        
+
         TEST_METHOD(SpecialChars)
         {
             append("\\\"\b\f\n\r\t");
             assertResultIs("\"\\\\\\\"\\b\\f\\n\\r\\t\"");
         }
-        
-        void append(const char* s)
+
+        TEST_METHOD(Number)
         {
-            sb->appendEscaped(s);
+            append(3.14);
+            assertResultIs("3.14");
+        }
+
+        template
+        void append(T value)
+        {
+            JsonValue(value).writeTo(*sb);
         }
 
         void assertResultIs(const char* expected)
diff --git a/JsonGeneratorTests/StringBuilder.cpp b/JsonGeneratorTests/StringBuilder.cpp
index 610c9fc7..f7d2058b 100644
--- a/JsonGeneratorTests/StringBuilder.cpp
+++ b/JsonGeneratorTests/StringBuilder.cpp
@@ -3,27 +3,10 @@
  * Benoit Blanchon 2014 - MIT License
  */
 
-#include 
-#include 
-
 #include "StringBuilder.h"
 
-void StringBuilder::append(double value)
-{
-    char* tail = buffer + length;
-
-    _snprintf(tail, capacity - length, "%lg", value);
-
-    length += strlen(tail);
-}
-
 void StringBuilder::append(const char* s)
 {
-    if (!s)
-    {
-        return append("null");        
-    }
-
     char* tail = buffer + length;
 
     while (*s && length= capacity) return;
 
-    if (length > capacity - 2)
-    {
-        // not enough from for quotes
-        return;
-    }
-
-    buffer[length++] = '"';
-
-    // keep one slot for the end quote
-    capacity--;
-
-    while (*s && length < capacity)
-    {
-        switch (*s)
-        {
-        case '"':
-            append("\\\"");
-            break;
-
-        case '\\':
-            append("\\\\");
-            break;
-
-        case '\b':
-            append("\\b");
-            break;
-
-        case '\f':
-            append("\\f");
-            break;
-
-        case '\n':
-            append("\\n");
-            break;
-
-        case '\r':
-            append("\\r");
-            break;
-
-        case '\t':
-            append("\\t");
-            break;
-
-        default:
-            buffer[length++] = *s;
-            break;
-        }
-
-        s++;
-    }
-
-    buffer[length++] = '"';
+    buffer[length++] = c;
     buffer[length] = 0;
-
-    // restore the original capacity
-    capacity++;
 }
\ No newline at end of file
diff --git a/JsonGeneratorTests/StringBuilder.h b/JsonGeneratorTests/StringBuilder.h
index 83989c73..886ac063 100644
--- a/JsonGeneratorTests/StringBuilder.h
+++ b/JsonGeneratorTests/StringBuilder.h
@@ -5,22 +5,38 @@
 
 #pragma once
 
-class StringBuilder
+#include "JsonSink.h"
+
+class StringBuilder : public JsonSink
 {
 public:
-    StringBuilder(char* buf, size_t size)
+    StringBuilder(char* buf, int size)
         : buffer(buf), capacity(size-1), length(0)
     {
         buffer[0] = 0;
     }
 
-    void append(double);
-    void append(const char* s);
-    void appendEscaped(const char* s);
+    virtual void append(char c);
+    virtual void append(const char* s);
+
+    virtual bool hasRoomFor(int n)
+    {
+        return capacity - length >= n;
+    }
+
+    virtual void reserveRoom(int n)
+    {
+        capacity -= n;
+    }
+
+    virtual void releaseRoom(int n)
+    {
+        capacity += n;
+    }
 
 private:
     char* buffer;
-    size_t capacity;
-    size_t length;
+    int capacity;
+    int length;
 };
 
diff --git a/JsonGeneratorTests/StringBuilderAppendTests.cpp b/JsonGeneratorTests/StringBuilderAppendTests.cpp
deleted file mode 100644
index 0730d3a6..00000000
--- a/JsonGeneratorTests/StringBuilderAppendTests.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "CppUnitTest.h"
-#include "StringBuilder.h"
-
-using namespace Microsoft::VisualStudio::CppUnitTestFramework;
-
-namespace JsonGeneratorTests
-{
-    TEST_CLASS(StringBuilderAppendTests)
-    {
-        char buffer[16];
-        StringBuilder* sb;
-
-    public:
-
-        TEST_METHOD_INITIALIZE(Initialize)
-        {
-            sb = new StringBuilder(buffer, sizeof(buffer));
-        }
-        
-        TEST_METHOD(InitialState)
-        {
-            assertResultIs("");
-        }
-
-        TEST_METHOD(EmptyString)
-        {
-            append("");
-            assertResultIs("");
-        }
-        
-        TEST_METHOD(Null)
-        {
-            append((char*)0);
-            assertResultIs("null");
-        }
-
-        TEST_METHOD(Number)
-        {
-            append(3.14);
-            assertResultIs("3.14");
-        }
-
-        TEST_METHOD(OneString)
-        {
-            append("ABCD");
-            assertResultIs("ABCD");
-        }
-
-        TEST_METHOD(TwoStrings)
-        {
-            append("ABCD");
-            append("EFGH");
-            assertResultIs("ABCDEFGH");
-        }
-
-        TEST_METHOD(OverCapacity)
-        {
-            append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-            assertResultIs("ABCDEFGHIJKLMNO");
-        }
-
-        TEST_METHOD(SpecialChars)
-        {
-            append("\\\"\b\f\n\r");
-            assertResultIs("\\\"\b\f\n\r");
-        }
-
-        void append(double d)
-        {
-            sb->append(d);
-        }
-
-        void append(const char* s)
-        {
-            sb->append(s);
-        }
-
-        void assertResultIs(const char* expected)
-        {
-            Assert::AreEqual(expected, buffer);
-        }
-    };
-}
\ No newline at end of file