Support for null variable values
diff --git a/src/main/java/org/apache/sling/feature/io/json/JSONReaderBase.java b/src/main/java/org/apache/sling/feature/io/json/JSONReaderBase.java
index 5413070..3d8405f 100644
--- a/src/main/java/org/apache/sling/feature/io/json/JSONReaderBase.java
+++ b/src/main/java/org/apache/sling/feature/io/json/JSONReaderBase.java
@@ -16,6 +16,20 @@
  */
 package org.apache.sling.feature.io.json;
 
+import org.apache.felix.configurator.impl.json.JSMin;
+import org.apache.felix.configurator.impl.json.JSONUtil;
+import org.apache.felix.configurator.impl.json.TypeConverter;
+import org.apache.felix.configurator.impl.model.Config;
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Bundles;
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.Configurations;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Extensions;
+import org.apache.sling.feature.KeyValueMap;
+
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringWriter;
@@ -39,20 +53,6 @@
 import javax.json.JsonStructure;
 import javax.json.JsonWriter;
 
-import org.apache.felix.configurator.impl.json.JSMin;
-import org.apache.felix.configurator.impl.json.JSONUtil;
-import org.apache.felix.configurator.impl.json.TypeConverter;
-import org.apache.felix.configurator.impl.model.Config;
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Bundles;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Extensions;
-import org.apache.sling.feature.KeyValueMap;
-
 /**
  * Common methods for JSON reading.
  */
@@ -154,13 +154,16 @@
             @SuppressWarnings("unchecked")
             final Map<String, Object> vars = (Map<String, Object>) variablesObj;
             for (final Map.Entry<String, Object> entry : vars.entrySet()) {
-                checkType("variable value", entry.getValue(), String.class, Boolean.class, Number.class);
+                Object val = entry.getValue();
+                checkType("variable value", val, String.class, Boolean.class, Number.class, null);
 
                 String key = entry.getKey();
                 if (kvMap.get(key) != null) {
                     throw new IOException(this.exceptionPrefix + "Duplicate variable " + key);
                 }
-                String value = entry.getValue().toString();
+
+                String value = val == null ? null : val.toString();
+
                 kvMap.put(key, value);
                 variables.put(key, value);
             }
@@ -466,12 +469,16 @@
      * Check if the value is one of the provided types
      * @param key A key for the error message
      * @param val The value to check
-     * @param types The allowed types
+     * @param types The allowed types, can also include {@code null} if null is an allowed value.
      * @throws IOException If the val is not of the specified types
      */
     protected void checkType(final String key, final Object val, Class<?>...types) throws IOException {
         boolean valid = false;
         for(final Class<?> c : types) {
+            if ( c == null && val == null) {
+                valid = true;
+                break;
+            }
             if ( c.isInstance(val) ) {
                 valid = true;
                 break;
diff --git a/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java b/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
index 9b7378b..9c77301 100644
--- a/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
+++ b/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
@@ -179,7 +179,11 @@
         if ( !vars.isEmpty()) {
             JsonObjectBuilder varsObj = Json.createObjectBuilder();
             for (final Map.Entry<String, String> entry : vars) {
-                varsObj.add(entry.getKey(), entry.getValue());
+                String val = entry.getValue();
+                if (val != null)
+                    varsObj.add(entry.getKey(), val);
+                else
+                    varsObj.addNull(entry.getKey());
             }
             ob.add(JSONConstants.FEATURE_VARIABLES, varsObj.build());
         }
diff --git a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java b/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java
index 1e451ea..3cf8618 100644
--- a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java
+++ b/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java
@@ -16,18 +16,18 @@
  */
 package org.apache.sling.feature.io.json;
 
-import static org.junit.Assert.assertEquals;
+import org.apache.sling.feature.Feature;
+import org.junit.Test;
 
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.Arrays;
 
-import org.apache.sling.feature.Feature;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
 
 public class FeatureJSONWriterTest {
 
-    @Test public void testRead() throws Exception {
+    @Test public void testWrite() throws Exception {
         final Feature f = U.readFeature("test");
         final Feature rf;
         try ( final StringWriter writer = new StringWriter() ) {
@@ -44,6 +44,20 @@
                 U.findCapability(rf.getCapabilities(), "osgi.service").getAttributes().get("objectClass"));
     }
 
+    @Test public void testWrite2() throws Exception {
+        final Feature f = U.readFeature("test2");
+
+        final Feature rf;
+        try ( final StringWriter writer = new StringWriter() ) {
+            FeatureJSONWriter.write(writer, f);
+            try ( final StringReader reader = new StringReader(writer.toString()) ) {
+                rf = FeatureJSONReader.read(reader, null);
+            }
+        }
+
+        assertEquals(f.getVariables(), rf.getVariables());
+    }
+
     @Test public void testExtensionsWriteRead() throws Exception {
         final Feature f = U.readFeature("artifacts-extension");
         final Feature rf;
diff --git a/src/test/resources/features/test2.json b/src/test/resources/features/test2.json
new file mode 100644
index 0000000..d89a051
--- /dev/null
+++ b/src/test/resources/features/test2.json
@@ -0,0 +1,7 @@
+{
+    "id" : "org.apache.sling/test-feature2/1.0.0.0",
+    "variables": {
+        "foo": "bar",
+        "zar": null
+    }
+}
\ No newline at end of file