You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2018/09/20 12:49:49 UTC

[sling-org-apache-sling-feature-io] branch streaming-json created (now a230049)

This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a change to branch streaming-json
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-io.git.


      at a230049  SLING-7941 - Use streaming APIs to marshall the Feature to JSON

This branch includes the following new commits:

     new a230049  SLING-7941 - Use streaming APIs to marshall the Feature to JSON

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-feature-io] 01/01: SLING-7941 - Use streaming APIs to marshall the Feature to JSON

Posted by si...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a commit to branch streaming-json
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-io.git

commit a230049634d7bb9cb21174235f0c77944cefdc95
Author: Simo Tripodi <st...@adobe.com>
AuthorDate: Thu Sep 20 14:49:34 2018 +0200

    SLING-7941 - Use streaming APIs to marshall the Feature to JSON
    
    initial check-in
---
 .../feature/io/json/ConfigurationJSONWriter.java   |  22 +-
 .../sling/feature/io/json/FeatureJSONWriter.java   | 249 +++++++++++----------
 .../sling/feature/io/json/JSONWriterBase.java      | 129 ++++++-----
 3 files changed, 206 insertions(+), 194 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
index 64e937d..3732a5e 100644
--- a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
+++ b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
@@ -16,18 +16,13 @@
  */
 package org.apache.sling.feature.io.json;
 
-import org.apache.sling.feature.Configurations;
-
 import java.io.IOException;
 import java.io.Writer;
-import java.util.Collections;
 
-import javax.json.Json;
-import javax.json.JsonObjectBuilder;
-import javax.json.JsonWriter;
-import javax.json.JsonWriterFactory;
 import javax.json.stream.JsonGenerator;
 
+import org.apache.sling.feature.Configurations;
+
 
 /**
  * JSON writer for configurations
@@ -49,16 +44,13 @@ public class ConfigurationJSONWriter extends JSONWriterBase {
 
     private void writeConfigurations(final Writer writer, final Configurations configs)
     throws IOException {
-        JsonObjectBuilder ob = Json.createObjectBuilder();
+        JsonGenerator generator = newGenerator(writer);
 
         // TODO is this correct?
-        ob.add(JSONConstants.FEATURE_CONFIGURATIONS,
-                writeConfigurationsMap(configs));
+        generator.writeStartObject(JSONConstants.FEATURE_CONFIGURATIONS);
+        writeConfigurations(generator, configs);
+        generator.writeEnd();
 
-        JsonWriterFactory writerFactory = Json.createWriterFactory(
-                Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
-        JsonWriter jw = writerFactory.createWriter(writer);
-        jw.writeObject(ob.build());
-        jw.close();
+        generator.close();
     }
 }
diff --git a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java b/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java
index 6d1776b..d008a7c 100644
--- a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java
+++ b/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java
@@ -18,15 +18,10 @@ package org.apache.sling.feature.io.json;
 
 import java.io.IOException;
 import java.io.Writer;
-import java.util.Collections;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
-import javax.json.Json;
-import javax.json.JsonArrayBuilder;
-import javax.json.JsonObjectBuilder;
-import javax.json.JsonWriter;
-import javax.json.JsonWriterFactory;
 import javax.json.stream.JsonGenerator;
 
 import org.apache.sling.feature.ArtifactId;
@@ -56,131 +51,151 @@ public class FeatureJSONWriter extends JSONWriterBase {
         w.writeFeature(writer, feature);
     }
 
-    private void writeProperty(final JsonObjectBuilder ob, final String key, final String value) {
+    private void writeProperty(final JsonGenerator generator, final String key, final String value) {
         if ( value != null ) {
-            ob.add(key, value);
+            generator.write(key, value);
         }
     }
 
-    private void writeFeature(final Writer writer, final Feature feature)
-    throws IOException {
-        JsonObjectBuilder ob = Json.createObjectBuilder();
-        ob.add(JSONConstants.FEATURE_ID, feature.getId().toMvnId());
-
-        // title, description, vendor, license
-        writeProperty(ob, JSONConstants.FEATURE_TITLE, feature.getTitle());
-        writeProperty(ob, JSONConstants.FEATURE_DESCRIPTION, feature.getDescription());
-        writeProperty(ob, JSONConstants.FEATURE_VENDOR, feature.getVendor());
-        writeProperty(ob, JSONConstants.FEATURE_LICENSE, feature.getLicense());
+    private <T> void writeList(final JsonGenerator generator, final String name, final Collection<T> values) {
+        if (!values.isEmpty()) {
+            generator.writeStartArray(name);
+            for (T value : values) {
+                generator.write(value.toString());
+            }
+            generator.writeEnd();
+        }
+    }
 
-        // variables
-        writeVariables(ob, feature.getVariables());
+    private void writeIncludes(final JsonGenerator generator, final List<Include> includes) {
+        if (includes.isEmpty()) {
+            return;
+        }
 
-        // includes
-        if ( !feature.getIncludes().isEmpty() ) {
-            JsonArrayBuilder incArray = Json.createArrayBuilder();
-            for(final Include inc : feature.getIncludes()) {
-                if ( inc.getArtifactExtensionRemovals().isEmpty()
-                     && inc.getBundleRemovals().isEmpty()
-                     && inc.getConfigurationRemovals().isEmpty()
-                     && inc.getFrameworkPropertiesRemovals().isEmpty() ) {
-                    incArray.add(inc.getId().toMvnId());
-                } else {
-                    JsonObjectBuilder includeObj = Json.createObjectBuilder();
-                    includeObj.add(JSONConstants.ARTIFACT_ID, inc.getId().toMvnId());
-
-                    JsonObjectBuilder removalsObj = Json.createObjectBuilder();
-                    if ( !inc.getArtifactExtensionRemovals().isEmpty()
-                         || inc.getExtensionRemovals().isEmpty() ) {
-                        JsonArrayBuilder extRemovals = Json.createArrayBuilder();
-                        for(final String id : inc.getExtensionRemovals()) {
-                            extRemovals.add(id);
-                        }
-                        for(final Map.Entry<String, List<ArtifactId>> entry : inc.getArtifactExtensionRemovals().entrySet()) {
-                            JsonArrayBuilder ab = Json.createArrayBuilder();
-                            for(final ArtifactId id : entry.getValue()) {
-                                ab.add(id.toMvnId());
-                            }
-                            extRemovals.add(Json.createObjectBuilder().add(entry.getKey(),
-                                    ab.build()).build());
-                        }
-                        removalsObj.add(JSONConstants.INCLUDE_EXTENSION_REMOVALS, extRemovals.build());
+        generator.writeStartArray(JSONConstants.FEATURE_INCLUDES);
+
+        for(final Include inc : includes) {
+            if ( inc.getArtifactExtensionRemovals().isEmpty()
+                 && inc.getBundleRemovals().isEmpty()
+                 && inc.getConfigurationRemovals().isEmpty()
+                 && inc.getFrameworkPropertiesRemovals().isEmpty() ) {
+                generator.write(inc.getId().toMvnId());
+            } else {
+                generator.writeStartObject();
+                //JsonObjectBuilder includeObj = Json.createObjectBuilder();
+                writeProperty(generator, JSONConstants.ARTIFACT_ID, inc.getId().toMvnId());
+
+                generator.writeStartObject(JSONConstants.INCLUDE_REMOVALS);
+
+                //JsonObjectBuilder removalsObj = Json.createObjectBuilder();
+                if ( !inc.getArtifactExtensionRemovals().isEmpty()
+                     || inc.getExtensionRemovals().isEmpty() ) {
+                    //JsonArrayBuilder extRemovals = Json.createArrayBuilder();
+                    generator.writeStartArray(JSONConstants.INCLUDE_EXTENSION_REMOVALS);
+
+                    for(final String id : inc.getExtensionRemovals()) {
+                        generator.write(id);
                     }
-                    if ( !inc.getConfigurationRemovals().isEmpty() ) {
-                        JsonArrayBuilder cfgRemovals = Json.createArrayBuilder();
-                        for(final String val : inc.getConfigurationRemovals()) {
-                            cfgRemovals.add(val);
-                        }
-                        removalsObj.add(JSONConstants.FEATURE_CONFIGURATIONS, cfgRemovals.build());
-                    }
-                    if ( !inc.getBundleRemovals().isEmpty() ) {
-                        JsonArrayBuilder bundleRemovals = Json.createArrayBuilder();
-                        for(final ArtifactId val : inc.getBundleRemovals()) {
-                            bundleRemovals.add(val.toMvnId());
-                        }
-                        removalsObj.add(JSONConstants.FEATURE_BUNDLES, bundleRemovals.build());
-                    }
-                    if ( !inc.getFrameworkPropertiesRemovals().isEmpty() ) {
-                        JsonArrayBuilder propRemovals = Json.createArrayBuilder();
-                        for(final String val : inc.getFrameworkPropertiesRemovals()) {
-                            propRemovals.add(val);
-                        }
-                        removalsObj.add(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, propRemovals.build());
+                    for(final Map.Entry<String, List<ArtifactId>> entry : inc.getArtifactExtensionRemovals().entrySet()) {
+                        generator.writeStartObject();
+
+                        writeList(generator, entry.getKey(), entry.getValue());
+
+                        generator.writeEnd(); 
                     }
-                    includeObj.add(JSONConstants.INCLUDE_REMOVALS, removalsObj.build());
 
-                    incArray.add(includeObj.build());
+                    generator.writeEnd();
                 }
+                writeList(generator, JSONConstants.FEATURE_CONFIGURATIONS, inc.getConfigurationRemovals());
+                writeList(generator, JSONConstants.FEATURE_BUNDLES, inc.getBundleRemovals());
+                writeList(generator, JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, inc.getFrameworkPropertiesRemovals());
+
+                generator.writeEnd();
             }
-            ob.add(JSONConstants.FEATURE_INCLUDES, incArray.build());
         }
 
-        // requirements
-        if ( !feature.getRequirements().isEmpty() ) {
-            JsonArrayBuilder requirements = Json.createArrayBuilder();
-
-            for(final Requirement req : feature.getRequirements()) {
-                JsonObjectBuilder requirementObj = Json.createObjectBuilder();
-                requirementObj.add(JSONConstants.REQCAP_NAMESPACE, req.getNamespace());
-                if ( !req.getAttributes().isEmpty() ) {
-                    JsonObjectBuilder attrObj = Json.createObjectBuilder();
-                    req.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, attrObj::add));
-                    requirementObj.add(JSONConstants.REQCAP_ATTRIBUTES, attrObj.build());
-                }
-                if ( !req.getDirectives().isEmpty() ) {
-                    JsonObjectBuilder reqObj = Json.createObjectBuilder();
-                    req.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, reqObj::add));
-                    requirementObj.add(JSONConstants.REQCAP_DIRECTIVES, reqObj.build());
-                }
-                requirements.add(requirementObj.build());
+        generator.writeEnd();
+    }
+
+    private void writeRequirements(final JsonGenerator generator, final List<Requirement> requirements) {
+        if (requirements.isEmpty()) {
+            return;
+        }
+
+        generator.writeStartArray(JSONConstants.FEATURE_REQUIREMENTS);
+
+        for(final Requirement req : requirements) {
+            generator.writeStartObject();
+            writeProperty(generator, JSONConstants.REQCAP_NAMESPACE, req.getNamespace());
+            if ( !req.getAttributes().isEmpty() ) {
+                generator.writeStartObject(JSONConstants.REQCAP_ATTRIBUTES);
+                req.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, generator::write));
+                generator.writeEnd();
+            }
+            if ( !req.getDirectives().isEmpty() ) {
+                generator.writeStartObject(JSONConstants.REQCAP_DIRECTIVES);
+                req.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, generator::write));
+                generator.writeEnd();
             }
-            ob.add(JSONConstants.FEATURE_REQUIREMENTS, requirements.build());
+            generator.writeEnd();
         }
 
-        // capabilities
-        if ( !feature.getCapabilities().isEmpty() ) {
-            JsonArrayBuilder capabilities = Json.createArrayBuilder();
-
-            for(final Capability cap : feature.getCapabilities()) {
-                JsonObjectBuilder capabilityObj = Json.createObjectBuilder();
-                capabilityObj.add(JSONConstants.REQCAP_NAMESPACE, cap.getNamespace());
-                if ( !cap.getAttributes().isEmpty() ) {
-                    JsonObjectBuilder attrObj = Json.createObjectBuilder();
-                    cap.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, attrObj::add));
-                    capabilityObj.add(JSONConstants.REQCAP_ATTRIBUTES, attrObj.build());
-                }
-                if ( !cap.getDirectives().isEmpty() ) {
-                    JsonObjectBuilder reqObj = Json.createObjectBuilder();
-                    cap.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, reqObj::add));
-                    capabilityObj.add(JSONConstants.REQCAP_DIRECTIVES, reqObj.build());
-                }
-                capabilities.add(capabilityObj.build());
+        generator.writeEnd();
+    }
+
+    private void writeCapabilities(final JsonGenerator generator, final List<Capability> capabilities) {
+        if (capabilities.isEmpty()) {
+            return;
+        }
+
+        generator.writeStartArray(JSONConstants.FEATURE_CAPABILITIES);
+
+        for(final Capability cap : capabilities) {
+            generator.writeStartObject();
+            writeProperty(generator, JSONConstants.REQCAP_NAMESPACE, cap.getNamespace());
+            if ( !cap.getAttributes().isEmpty() ) {
+                generator.writeStartObject(JSONConstants.REQCAP_ATTRIBUTES);
+                cap.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, generator::write));
+                generator.writeEnd();
+            }
+            if ( !cap.getDirectives().isEmpty() ) {
+                generator.writeStartObject(JSONConstants.REQCAP_DIRECTIVES);
+                cap.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, generator::write));
+                generator.writeEnd();
             }
-            ob.add(JSONConstants.FEATURE_CAPABILITIES, capabilities.build());
+            generator.writeEnd();
         }
 
+        generator.writeEnd();
+    }
+
+    private void writeFeature(final Writer writer, final Feature feature)
+    throws IOException {
+        JsonGenerator generator = newGenerator(writer);
+        generator.writeStartObject();
+
+        writeProperty(generator, JSONConstants.FEATURE_ID, feature.getId().toMvnId());
+
+        // title, description, vendor, license
+        writeProperty(generator, JSONConstants.FEATURE_TITLE, feature.getTitle());
+        writeProperty(generator, JSONConstants.FEATURE_DESCRIPTION, feature.getDescription());
+        writeProperty(generator, JSONConstants.FEATURE_VENDOR, feature.getVendor());
+        writeProperty(generator, JSONConstants.FEATURE_LICENSE, feature.getLicense());
+
+        // variables
+        writeVariables(generator, feature.getVariables());
+
+        // includes
+        writeIncludes(generator, feature.getIncludes());
+
+        // requirements
+        writeRequirements(generator, feature.getRequirements());
+
+        // capabilities
+        writeCapabilities(generator, feature.getCapabilities());
+
         // bundles
-        writeBundles(ob, feature.getBundles(), feature.getConfigurations());
+        writeBundles(generator, feature.getBundles(), feature.getConfigurations());
 
         // configurations
         final Configurations cfgs = new Configurations();
@@ -190,18 +205,14 @@ public class FeatureJSONWriter extends JSONWriterBase {
                 cfgs.add(cfg);
             }
         }
-        writeConfigurations(ob, cfgs);
+        writeConfigurations(generator, cfgs);
 
         // framework properties
-        writeFrameworkProperties(ob, feature.getFrameworkProperties());
+        writeFrameworkProperties(generator, feature.getFrameworkProperties());
 
         // extensions
-        writeExtensions(ob, feature.getExtensions(), feature.getConfigurations());
+        writeExtensions(generator, feature.getExtensions(), feature.getConfigurations());
 
-        JsonWriterFactory writerFactory = Json.createWriterFactory(
-                Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
-        JsonWriter jw = writerFactory.createWriter(writer);
-        jw.writeObject(ob.build());
-        jw.close();
+        generator.writeEnd().close();
     }
 }
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 9c77301..ecfebb8 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
@@ -17,16 +17,17 @@
 package org.apache.sling.feature.io.json;
 
 import java.io.StringReader;
+import java.io.Writer;
 import java.lang.reflect.Array;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
 
 import javax.json.Json;
-import javax.json.JsonArrayBuilder;
-import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
 import javax.json.JsonStructure;
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
 
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.Bundles;
@@ -41,12 +42,19 @@ import org.apache.sling.feature.KeyValueMap;
  */
 abstract class JSONWriterBase {
 
-    protected void writeBundles(final JsonObjectBuilder ob,
+    private final JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
+
+    protected final JsonGenerator newGenerator(final Writer writer) {
+        return generatorFactory.createGenerator(writer);
+    }
+
+    protected void writeBundles(final JsonGenerator generator,
             final Bundles bundles,
             final Configurations allConfigs) {
         // bundles
         if ( !bundles.isEmpty() ) {
-            JsonArrayBuilder bundleArray = Json.createArrayBuilder();
+            generator.writeStartArray(JSONConstants.FEATURE_BUNDLES);
+            //JsonArrayBuilder bundleArray = Json.createArrayBuilder();
 
             for(final Artifact artifact : bundles) {
                 final Configurations cfgs = new Configurations();
@@ -58,21 +66,21 @@ abstract class JSONWriterBase {
                 }
                 KeyValueMap md = artifact.getMetadata();
                 if ( md.isEmpty() && cfgs.isEmpty() ) {
-                    bundleArray.add(artifact.getId().toMvnId());
+                    generator.write(artifact.getId().toMvnId());
                 } else {
-                    JsonObjectBuilder bundleObj = Json.createObjectBuilder();
-                    bundleObj.add(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
+                    generator.writeStartObject();
+                    generator.write(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
 
                     for(final Map.Entry<String, String> me : md) {
-                        bundleObj.add(me.getKey(), me.getValue());
+                        generator.write(me.getKey(), me.getValue());
                     }
 
-                    writeConfigurations(bundleObj, cfgs);
-
-                    bundleArray.add(bundleObj.build());
+                    generator.writeEnd();
                 }
             }
-            ob.add(JSONConstants.FEATURE_BUNDLES, bundleArray.build());
+            //ob.add(JSONConstants.FEATURE_BUNDLES, bundleArray.build());
+
+            generator.writeEnd();
         }
     }
 
@@ -81,20 +89,13 @@ abstract class JSONWriterBase {
      * @param ob The json generator
      * @param cfgs The list of configurations
      */
-    protected void writeConfigurations(final JsonObjectBuilder ob, final Configurations cfgs) {
-        if ( !cfgs.isEmpty() ) {
-            ob.add(JSONConstants.FEATURE_CONFIGURATIONS,
-                    writeConfigurationsMap(cfgs));
+    protected void writeConfigurations(final JsonGenerator generator, final Configurations cfgs) {
+        if ( cfgs.isEmpty() ) {
+            return;
         }
-    }
 
-    /**
-     * Write the list of configurations into a "configurations" element
-     * @param cfgs The list of configurations.
-     * @return The JSON element containing the configurations.
-     */
-    protected JsonObject writeConfigurationsMap(final Configurations cfgs) {
-        JsonObjectBuilder configObj = Json.createObjectBuilder();
+        generator.writeStartObject(JSONConstants.FEATURE_CONFIGURATIONS);
+
         for(final Configuration cfg : cfgs) {
             final String key;
             if ( cfg.isFactoryConfiguration() ) {
@@ -102,7 +103,8 @@ abstract class JSONWriterBase {
             } else {
                 key = cfg.getPid();
             }
-            JsonObjectBuilder cfgValObj = Json.createObjectBuilder();
+
+            generator.writeStartObject(key);
 
             final Enumeration<String> e = cfg.getProperties().keys();
             while ( e.hasMoreElements() ) {
@@ -136,71 +138,77 @@ abstract class JSONWriterBase {
                 }
 
                 if ( val.getClass().isArray() ) {
-                    JsonArrayBuilder ab = Json.createArrayBuilder();
+                    generator.writeStartArray(name);
+                    // JsonArrayBuilder ab = Json.createArrayBuilder();
                     for(int i=0; i<Array.getLength(val);i++ ) {
                         final Object obj = Array.get(val, i);
                         if ( typePostFix == null ) {
                             if ( obj instanceof String ) {
-                                ab.add((String)obj);
+                                generator.write((String)obj);
                             } else if ( obj instanceof Boolean ) {
-                                ab.add((Boolean)obj);
+                                generator.write((Boolean)obj);
                             } else if ( obj instanceof Long ) {
-                                ab.add((Long)obj);
+                                generator.write((Long)obj);
                             } else if ( obj instanceof Double ) {
-                                ab.add((Double)obj);
+                                generator.write((Double)obj);
                             }
                         } else {
-                            ab.add(obj.toString());
+                            generator.write(obj.toString());
                         }
                     }
-                    cfgValObj.add(name, ab.build());
+
+                    generator.writeEnd();
                 } else {
                     if ( typePostFix == null ) {
                         if ( val instanceof String ) {
-                            cfgValObj.add(name, (String)val);
+                            generator.write(name, (String)val);
                         } else if ( val instanceof Boolean ) {
-                            cfgValObj.add(name, (Boolean)val);
+                            generator.write(name, (Boolean)val);
                         } else if ( val instanceof Long ) {
-                            cfgValObj.add(name, (Long)val);
+                            generator.write(name, (Long)val);
                         } else if ( val instanceof Double ) {
-                            cfgValObj.add(name, (Double)val);
+                            generator.write(name, (Double)val);
                         }
                     } else {
-                        cfgValObj.add(name + typePostFix, val.toString());
+                        generator.write(name + typePostFix, val.toString());
                     }
                 }
             }
-            configObj.add(key, cfgValObj.build());
+
+            generator.writeEnd();
         }
-        return configObj.build();
+
+        generator.writeEnd();
     }
 
-    protected void writeVariables(final JsonObjectBuilder ob, final KeyValueMap vars) {
+    protected void writeVariables(final JsonGenerator generator, final KeyValueMap vars) {
         if ( !vars.isEmpty()) {
-            JsonObjectBuilder varsObj = Json.createObjectBuilder();
+            generator.writeStartObject(JSONConstants.FEATURE_VARIABLES);
+
             for (final Map.Entry<String, String> entry : vars) {
                 String val = entry.getValue();
                 if (val != null)
-                    varsObj.add(entry.getKey(), val);
+                    generator.write(entry.getKey(), val);
                 else
-                    varsObj.addNull(entry.getKey());
+                    generator.writeNull(entry.getKey());
             }
-            ob.add(JSONConstants.FEATURE_VARIABLES, varsObj.build());
+
+            generator.writeEnd();
         }
     }
 
-    protected void writeFrameworkProperties(final JsonObjectBuilder ob, final KeyValueMap props) {
+    protected void writeFrameworkProperties(final JsonGenerator generator, final KeyValueMap props) {
         // framework properties
         if ( !props.isEmpty() ) {
-            JsonObjectBuilder propsObj = Json.createObjectBuilder();
+            generator.writeStartObject(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES);
             for(final Map.Entry<String, String> entry : props) {
-                propsObj.add(entry.getKey(), entry.getValue());
+                generator.write(entry.getKey(), entry.getValue());
             }
-            ob.add(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, propsObj.build());
+            generator.writeEnd();
         }
     }
 
-    protected void writeExtensions(final JsonObjectBuilder ob,
+    protected void writeExtensions(final JsonGenerator generator,
             final List<Extension> extensions,
             final Configurations allConfigs) {
         for(final Extension ext : extensions) {
@@ -210,11 +218,11 @@ abstract class JSONWriterBase {
                 try ( final StringReader reader = new StringReader(ext.getJSON()) ) {
                     struct = Json.createReader(reader).read();
                 }
-                ob.add(key, struct);
+                generator.write(key, struct);
             } else if ( ext.getType() == ExtensionType.TEXT ) {
-                ob.add(key, ext.getText());
+                generator.write(key, ext.getText());
             } else {
-                JsonArrayBuilder extensionArr = Json.createArrayBuilder();
+                generator.writeStartArray(key);
                 for(final Artifact artifact : ext.getArtifacts()) {
                     final Configurations artifactCfgs = new Configurations();
                     for(final Configuration cfg : allConfigs) {
@@ -224,20 +232,21 @@ abstract class JSONWriterBase {
                         }
                     }
                     if ( artifact.getMetadata().isEmpty() && artifactCfgs.isEmpty() ) {
-                        extensionArr.add(artifact.getId().toMvnId());
+                        generator.write(artifact.getId().toMvnId());
                     } else {
-                        JsonObjectBuilder extObj = Json.createObjectBuilder();
-                        extObj.add(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
+                        generator.writeStartObject();
+                        generator.write(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
 
                         for(final Map.Entry<String, String> me : artifact.getMetadata()) {
-                            extObj.add(me.getKey(), me.getValue());
+                            generator.write(me.getKey(), me.getValue());
                         }
 
-                        writeConfigurations(ob, artifactCfgs);
-                        extensionArr.add(extObj.build());
+                        writeConfigurations(generator, artifactCfgs);
+
+                        generator.writeEnd();
                     }
                 }
-                ob.add(key, extensionArr.build());
+                generator.writeEnd();
             }
         }
     }