You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ze...@apache.org on 2022/03/11 16:51:16 UTC

[incubator-streampipes] branch STREAMPIPES-514 created (now 3f3a9ca)

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

zehnder pushed a change to branch STREAMPIPES-514
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git.


      at 3f3a9ca  [STREAMPIPES-514] Rework format selection in Connect

This branch includes the following new commits:

     new 3f3a9ca  [STREAMPIPES-514] Rework format selection in Connect

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.


[incubator-streampipes] 01/01: [STREAMPIPES-514] Rework format selection in Connect

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

zehnder pushed a commit to branch STREAMPIPES-514
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit 3f3a9ca853dd4833c66faf728903cedcbed2b8b1
Author: Philipp Zehnder <ze...@fzi.de>
AuthorDate: Fri Mar 11 17:50:20 2022 +0100

    [STREAMPIPES-514] Rework format selection in Connect
---
 .../adapter/format/geojson/GeoJsonFormat.java      |  2 +
 .../adapter/format/json/AbstractJsonFormat.java    |  1 +
 .../adapter/format/json/arraykey/JsonFormat.java   |  3 +-
 .../format/json/arraynokey/JsonArrayFormat.java    |  3 +-
 .../format/json/object/JsonObjectFormat.java       |  5 +-
 .../model/connect/grounding/FormatDescription.java | 15 +++++-
 .../builder/adapter/FormatDescriptionBuilder.java  | 10 ++++
 .../src/lib/model/gen/streampipes-model-client.ts  |  2 +-
 .../src/lib/model/gen/streampipes-model.ts         | 14 +++---
 .../format-configuration.component.html            |  4 +-
 .../format-configuration.component.ts              | 12 +----
 .../format-item-json.component.html}               | 12 +++--
 .../format-item-json.component.scss                | 47 ++++++++++++++++++
 .../format-item-json/format-item-json.component.ts | 36 ++++++++++++++
 .../format-item/format-item.component.html         | 11 ++++-
 .../format-item/format-item.component.ts           | 10 ----
 .../format-list/format-list.component.html         | 32 +++++++++++--
 .../format-list/format-list.component.ts           | 56 +++++++++++++++++++---
 ui/src/app/connect/connect.module.ts               |  4 +-
 19 files changed, 227 insertions(+), 52 deletions(-)

diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/geojson/GeoJsonFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/geojson/GeoJsonFormat.java
index 40b4152..39465e1 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/geojson/GeoJsonFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/geojson/GeoJsonFormat.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.adapter.format.geojson;
 
+import org.apache.streampipes.connect.adapter.format.json.AbstractJsonFormat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
@@ -40,6 +41,7 @@ public class GeoJsonFormat implements IFormat {
     public FormatDescription declareModel() {
 
         return FormatDescriptionBuilder.create(ID, "GeoJSON", "Reads GeoJson")
+                .addFormatType(AbstractJsonFormat.JSON_FORMAT_TYPE)
                 .build();
 
     }
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
index eaf48a9..a7116ae 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/AbstractJsonFormat.java
@@ -26,6 +26,7 @@ import org.apache.streampipes.model.schema.EventSchema;
 import java.util.Map;
 
 public abstract class AbstractJsonFormat implements IFormat {
+  public static String JSON_FORMAT_TYPE = "json";
 
   @Override
   public Map<String, Object> parse(byte[] object) throws ParseException {
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraykey/JsonFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraykey/JsonFormat.java
index f226c06..fe53165 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraykey/JsonFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraykey/JsonFormat.java
@@ -38,7 +38,8 @@ public class JsonFormat extends AbstractJsonFormat {
     @Override
     public FormatDescription declareModel() {
 
-        return FormatDescriptionBuilder.create(ID, "Json Array Key", "Transforms objects within an array into events")
+        return FormatDescriptionBuilder.create(ID, "Array Field", "Use one property of the json object that is an array, e.g. {'arrayKey': [{'value': 1}, {'value': 2}]}")
+                .addFormatType(JSON_FORMAT_TYPE)
                 .requiredTextParameter(Labels.from("key","Key",
                         "Key of the array within the Json object"))
                 .build();
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraynokey/JsonArrayFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraynokey/JsonArrayFormat.java
index a956832..79b573a 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraynokey/JsonArrayFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/arraynokey/JsonArrayFormat.java
@@ -35,7 +35,8 @@ public class JsonArrayFormat extends AbstractJsonFormat {
 
     @Override
     public FormatDescription declareModel() {
-        return FormatDescriptionBuilder.create(ID, "Json Array No Key", "Transforms all objects within array to events")
+        return FormatDescriptionBuilder.create(ID, "Array", "Each event consists of only one array of json objects, e.g. [{'value': 1}, {'value': 2}]")
+                .addFormatType(JSON_FORMAT_TYPE)
                 .build();
     }
 
diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectFormat.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectFormat.java
index 9eeb69b..f5306bb 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectFormat.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/format/json/object/JsonObjectFormat.java
@@ -34,8 +34,9 @@ public class JsonObjectFormat extends AbstractJsonFormat {
 
   @Override
   public FormatDescription declareModel() {
-    return FormatDescriptionBuilder.create(ID, "Json Object", "Requires an enclosing Json Object")
-                .build();
+    return FormatDescriptionBuilder.create(ID, "Single Object", "Each event is a single json object (e.g. {'value': 1})")
+            .addFormatType(JSON_FORMAT_TYPE)
+            .build();
   }
 
   @Override
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/grounding/FormatDescription.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/grounding/FormatDescription.java
index cac5f91..ba6bb40 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/grounding/FormatDescription.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/grounding/FormatDescription.java
@@ -30,6 +30,8 @@ public class FormatDescription extends NamedStreamPipesEntity {
 
     private List<StaticProperty> config;
 
+    private String formatType = "";
+
     public FormatDescription() {
         super();
         this.config = new ArrayList<>();
@@ -40,14 +42,16 @@ public class FormatDescription extends NamedStreamPipesEntity {
         this.config = new ArrayList<>();
     }
 
-    public FormatDescription(String uri, String name, String description, List<StaticProperty> config) {
+    public FormatDescription(String uri, String name, String description, List<StaticProperty> config, String formatType) {
         super(uri, name, description);
         this.config = config;
+        this.formatType = formatType;
     }
 
     public FormatDescription(FormatDescription other) {
         super(other);
         this.config = new Cloner().staticProperties(other.getConfig());
+        this.formatType = other.getFormatType();
     }
 
     public void addConfig(StaticProperty sp) {
@@ -62,9 +66,18 @@ public class FormatDescription extends NamedStreamPipesEntity {
         this.config = config;
     }
 
+    public String getFormatType() {
+        return formatType;
+    }
+
+    public void setFormatType(String formatType) {
+        this.formatType = formatType;
+    }
+
     @Override
     public String toString() {
         return "FormatDescription{" +
+                "formatType=" + formatType +
                 "config=" + config +
                 '}';
     }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/FormatDescriptionBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/FormatDescriptionBuilder.java
index c7d3ff0..cfa5706 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/FormatDescriptionBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/adapter/FormatDescriptionBuilder.java
@@ -38,6 +38,16 @@ public class FormatDescriptionBuilder extends
     return new FormatDescriptionBuilder(id, label, description);
   }
 
+  /**
+   * Add a format type to the format description, e.g. json
+   * @param formatType
+   * @return
+   */
+  public FormatDescriptionBuilder addFormatType(String formatType) {
+    this.elementDescription.setFormatType(formatType);
+    return me();
+  }
+
   @Override
   protected FormatDescriptionBuilder me() {
     return this;
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
index b572c42..2793222 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
@@ -18,7 +18,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-02-02 13:46:18.
+// Generated using typescript-generator version 2.27.744 on 2022-03-11 16:37:33.
 
 export class ExtensionsServiceEndpointItem {
     appId: string;
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index a68c527..18a5649 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -18,7 +18,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-02-05 22:40:52.
+// Generated using typescript-generator version 2.27.744 on 2022-03-11 16:37:20.
 
 export class AbstractStreamPipesEntity {
     "@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStre [...]
@@ -192,8 +192,8 @@ export class AdapterDescription extends NamedStreamPipesEntity {
         instance.selectedEndpointUrl = data.selectedEndpointUrl;
         instance.correspondingServiceGroup = data.correspondingServiceGroup;
         instance.correspondingDataStreamElementId = data.correspondingDataStreamElementId;
-        instance.valueRules = __getCopyArrayFn(__identity<any>())(data.valueRules);
         instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
+        instance.valueRules = __getCopyArrayFn(__identity<any>())(data.valueRules);
         instance.schemaRules = __getCopyArrayFn(__identity<any>())(data.schemaRules);
         return instance;
     }
@@ -1589,6 +1589,7 @@ export class FixedOutputStrategy extends OutputStrategy {
 export class FormatDescription extends NamedStreamPipesEntity {
     "@class": "org.apache.streampipes.model.connect.grounding.FormatDescription";
     config: StaticPropertyUnion[];
+    formatType: string;
 
     static fromData(data: FormatDescription, target?: FormatDescription): FormatDescription {
         if (!data) {
@@ -1597,6 +1598,7 @@ export class FormatDescription extends NamedStreamPipesEntity {
         const instance = target || new FormatDescription();
         super.fromData(data, instance);
         instance.config = __getCopyArrayFn(StaticProperty.fromDataUnion)(data.config);
+        instance.formatType = data.formatType;
         return instance;
     }
 }
@@ -1666,9 +1668,9 @@ export class GenericAdapterSetDescription extends AdapterSetDescription implemen
         }
         const instance = target || new GenericAdapterSetDescription();
         super.fromData(data, instance);
-        instance.eventSchema = EventSchema.fromData(data.eventSchema);
         instance.formatDescription = FormatDescription.fromData(data.formatDescription);
         instance.protocolDescription = ProtocolDescription.fromData(data.protocolDescription);
+        instance.eventSchema = EventSchema.fromData(data.eventSchema);
         return instance;
     }
 }
@@ -1685,9 +1687,9 @@ export class GenericAdapterStreamDescription extends AdapterStreamDescription im
         }
         const instance = target || new GenericAdapterStreamDescription();
         super.fromData(data, instance);
-        instance.eventSchema = EventSchema.fromData(data.eventSchema);
         instance.formatDescription = FormatDescription.fromData(data.formatDescription);
         instance.protocolDescription = ProtocolDescription.fromData(data.protocolDescription);
+        instance.eventSchema = EventSchema.fromData(data.eventSchema);
         return instance;
     }
 }
@@ -2498,8 +2500,8 @@ export class PipelineTemplateDescription extends NamedStreamPipesEntity {
         const instance = target || new PipelineTemplateDescription();
         super.fromData(data, instance);
         instance.boundTo = __getCopyArrayFn(BoundPipelineElement.fromData)(data.boundTo);
-        instance.pipelineTemplateName = data.pipelineTemplateName;
         instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
+        instance.pipelineTemplateName = data.pipelineTemplateName;
         instance.pipelineTemplateId = data.pipelineTemplateId;
         return instance;
     }
@@ -2901,8 +2903,8 @@ export class SpDataSet extends SpDataStream {
         instance.datasetInvocationId = data.datasetInvocationId;
         instance.correspondingPipeline = data.correspondingPipeline;
         instance.selectedEndpointUrl = data.selectedEndpointUrl;
-        instance.brokerHostname = data.brokerHostname;
         instance.actualTopicName = data.actualTopicName;
+        instance.brokerHostname = data.brokerHostname;
         return instance;
     }
 }
diff --git a/ui/src/app/connect/components/format-configuration/format-configuration.component.html b/ui/src/app/connect/components/format-configuration/format-configuration.component.html
index a1ac028..13da938 100644
--- a/ui/src/app/connect/components/format-configuration/format-configuration.component.html
+++ b/ui/src/app/connect/components/format-configuration/format-configuration.component.html
@@ -23,13 +23,13 @@
     </div>
     <div class="sp-blue-border padding">
         <sp-format-list fxFlex="100"
-                        [allFormats]="allFormats"
                         (selectedFormatEmitter)="formatSelected($event)"
                         [selectedFormat]="selectedFormat">
         </sp-format-list>
     </div>
 
-    <div class="assemblyOptions sp-blue-bg">
+    <div class="assemblyOptions sp-blue-bg"
+         *ngIf="selectedFormat">
         <h4>Configure format</h4>
     </div>
 
diff --git a/ui/src/app/connect/components/format-configuration/format-configuration.component.ts b/ui/src/app/connect/components/format-configuration/format-configuration.component.ts
index 1ef937f..87a8c7c 100644
--- a/ui/src/app/connect/components/format-configuration/format-configuration.component.ts
+++ b/ui/src/app/connect/components/format-configuration/format-configuration.component.ts
@@ -59,11 +59,6 @@ export class FormatConfigurationComponent implements OnInit {
   selectedFormat: FormatDescription;
 
   /**
-   * Contains all the available formats that a user can select from
-   */
-  allFormats: FormatDescription[] = [];
-
-  /**
    * The form group to validate the configuration for the format
    */
   formatForm: FormGroup;
@@ -75,11 +70,6 @@ export class FormatConfigurationComponent implements OnInit {
 
   ngOnInit(): void {
 
-    // fetch all available formats from backend
-    this.restService.getFormats().subscribe(res => {
-      this.allFormats = res;
-    });
-
     // initialize form for validation
     this.formatForm = this._formBuilder.group({});
     this.formatForm.statusChanges.subscribe((status) => {
@@ -101,6 +91,8 @@ export class FormatConfigurationComponent implements OnInit {
         this.formatConfigurationValid = this.formatForm.valid;
       }
     }
+
+    this.formatConfigurationValid = false;
   }
 
   formatSelected(selectedFormat) {
diff --git a/ui/src/app/connect/components/format-item/format-item.component.html b/ui/src/app/connect/components/format-item-json/format-item-json.component.html
similarity index 74%
copy from ui/src/app/connect/components/format-item/format-item.component.html
copy to ui/src/app/connect/components/format-item-json/format-item-json.component.html
index 0edf190..5c36b30 100644
--- a/ui/src/app/connect/components/format-item/format-item.component.html
+++ b/ui/src/app/connect/components/format-item-json/format-item-json.component.html
@@ -16,6 +16,12 @@
   ~
   -->
 
-<div [attr.data-cy]="format.name.split(' ').join('_').toLowerCase()" *ngIf="!$any(format).edit || !hasConfig" class="format-box" (click)="formatEditable()" [ngClass]="{selectedItem: isSelected()}" fxFlex="100" fxLayout="column">
-    <div class="format-label"> {{format.name}} </div>
-</div>
\ No newline at end of file
+<div fxFlex="100"
+     fxLayout="column"
+     matTooltip="Select one of the supported json formats"
+     data-cy="connect-select-json-formats"
+     class="format-box"
+     [ngClass]="{selectedItem: isSelected}" >
+    <div class="format-label">Json</div>
+</div>
+
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.scss b/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
new file mode 100644
index 0000000..30123c0
--- /dev/null
+++ b/ui/src/app/connect/components/format-item-json/format-item-json.component.scss
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+.format-label {
+  line-height:50px;
+  margin: auto;
+  text-align: center;
+  font-weight: bold;
+  font-size: 1.3em;
+}
+
+.format-box {
+  min-height: 50px;
+  box-shadow: 1px 1px 2px #555;
+  border: 1px solid gray;
+  cursor: pointer;
+  padding: 10px;
+  opacity: 0.7;
+  margin: 10px;
+  background: #ffffff;
+}
+
+.format-box:hover {
+  opacity: 1;
+}
+
+.selectedItem {
+  opacity: 1;
+  background-color: grey;
+}
+
diff --git a/ui/src/app/connect/components/format-item-json/format-item-json.component.ts b/ui/src/app/connect/components/format-item-json/format-item-json.component.ts
new file mode 100644
index 0000000..cfc24c5
--- /dev/null
+++ b/ui/src/app/connect/components/format-item-json/format-item-json.component.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'sp-format-item-json',
+  templateUrl: './format-item-json.component.html',
+  styleUrls: ['./format-item-json.component.scss']
+})
+export class FormatItemJsonComponent implements OnInit {
+
+  @Input()
+  isSelected: boolean;
+
+  constructor() { }
+
+  ngOnInit(): void {
+  }
+
+}
diff --git a/ui/src/app/connect/components/format-item/format-item.component.html b/ui/src/app/connect/components/format-item/format-item.component.html
index 0edf190..db77998 100644
--- a/ui/src/app/connect/components/format-item/format-item.component.html
+++ b/ui/src/app/connect/components/format-item/format-item.component.html
@@ -16,6 +16,13 @@
   ~
   -->
 
-<div [attr.data-cy]="format.name.split(' ').join('_').toLowerCase()" *ngIf="!$any(format).edit || !hasConfig" class="format-box" (click)="formatEditable()" [ngClass]="{selectedItem: isSelected()}" fxFlex="100" fxLayout="column">
+<div fxFlex="100"
+     fxLayout="column"
+     matTooltip="{{format.description}}"
+     [attr.data-cy]="format.name.split(' ').join('_').toLowerCase()"
+     *ngIf="!$any(format).edit || !hasConfig"
+     class="format-box"
+     (click)="formatEditable()"
+     [ngClass]="{selectedItem: isSelected()}" >
     <div class="format-label"> {{format.name}} </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/ui/src/app/connect/components/format-item/format-item.component.ts b/ui/src/app/connect/components/format-item/format-item.component.ts
index 779a93e..6d7db60 100644
--- a/ui/src/app/connect/components/format-item/format-item.component.ts
+++ b/ui/src/app/connect/components/format-item/format-item.component.ts
@@ -51,16 +51,6 @@ export class FormatItemComponent {
 
   }
 
-  validateText(textValid) {
-    if (textValid && (this.format as any).edit) {
-      this.validateEmitter.emit(true);
-      this.selectedFormat = this.format;
-      this.selectedFormatEmitter.emit(this.selectedFormat);
-    } else {
-      this.validateEmitter.emit(false);
-      this.selectedFormat = null;
-    }
-  }
   isSelected(): boolean {
     if (!this.selectedFormat || !this.format) {
       return false;
diff --git a/ui/src/app/connect/components/format-list/format-list.component.html b/ui/src/app/connect/components/format-list/format-list.component.html
index d1e731d..59d46c2 100644
--- a/ui/src/app/connect/components/format-list/format-list.component.html
+++ b/ui/src/app/connect/components/format-list/format-list.component.html
@@ -17,11 +17,33 @@
   -->
 
 <div fxLayout="row wrap" fxLayoutAlign="start stretch">
-    <div fxFlex="33" *ngFor="let format of allFormats">
+
+    <div fxFlex="25">
+        <sp-format-item-json
+                [isSelected]="selectJsonFormats"
+                (click)="selectJsonFormat()"></sp-format-item-json>
+    </div>
+    <div fxFlex="25"
+         *ngFor="let format of allFormats">
+        <sp-format-item [format]="format" (validateEmitter)="validateAll($event)"
+                        (editableEmitter)="formatEditable($event)"
+                        [selectedFormat]="selectedFormat"
+                        (selectedFormatEmitter)="formatSelected($event)">
+        </sp-format-item>
+    </div>
+
+    <div fxFlex="100"
+         class="assemblyOptions sp-blue-bg"
+         *ngIf="selectJsonFormats">
+        <h4>Select json format</h4>
+    </div>
+
+    <div fxFlex="25"
+         *ngFor="let format of showJsonFormats">
         <sp-format-item [format]="format" (validateEmitter)="validateAll($event)"
-        (editableEmitter)="formatEditable($event)"
-        [selectedFormat]="selectedFormat"
-        (selectedFormatEmitter)="formatSelected($event)">
+                        (editableEmitter)="formatEditable($event)"
+                        [selectedFormat]="selectedFormat"
+                        (selectedFormatEmitter)="formatSelected($event)">
         </sp-format-item>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/ui/src/app/connect/components/format-list/format-list.component.ts b/ui/src/app/connect/components/format-list/format-list.component.ts
index e9c2493..bcc1afd 100644
--- a/ui/src/app/connect/components/format-list/format-list.component.ts
+++ b/ui/src/app/connect/components/format-list/format-list.component.ts
@@ -16,8 +16,9 @@
  *
  */
 
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { FormatDescription } from '@streampipes/platform-services';
+import { RestService } from '../../services/rest.service';
 
 @Component({
     selector: 'sp-format-list',
@@ -25,15 +26,42 @@ import { FormatDescription } from '@streampipes/platform-services';
     styleUrls: ['./format-list.component.scss']
   })
 
-export class FormatListComponent {
+export class FormatListComponent implements OnInit {
 
     @Input() public selectedFormat: FormatDescription;
-    @Input() allFormats: FormatDescription[];
 
     @Output() validateEmitter = new EventEmitter();
     @Output() public selectedFormatEmitter = new EventEmitter<FormatDescription>();
 
-    constructor() {
+    /**
+     * Contains all the available formats that a user can select from
+     */
+    allFormats: FormatDescription[] = [];
+
+    allJsonFormats: FormatDescription[] = [];
+    showJsonFormats: FormatDescription[] = [];
+
+    jsonFormatDescription = new FormatDescription();
+    selectJsonFormats = false;
+
+    constructor(private restService: RestService) {
+        this.jsonFormatDescription.name = 'Json';
+    }
+
+    ngOnInit(): void {
+        // fetch all available formats from backend
+        this.restService.getFormats().subscribe(res => {
+            // this.allFormats.push(jsonFormatDescription);
+            // split resulting formats up to only show one button for Json Formats
+            res.forEach(format => {
+                if (format.formatType !== 'json') {
+                    this.allFormats.push(format);
+                } else {
+                    this.allJsonFormats.push(format);
+                }
+            });
+        });
+
     }
 
     formatEditable(selectedFormat) {
@@ -44,9 +72,23 @@ export class FormatListComponent {
       });
     }
 
-    formatSelected(selectedFormat) {
-      this.selectedFormat = selectedFormat;
-      this.selectedFormatEmitter.emit(this.selectedFormat);
+    formatSelected(selectedFormat: FormatDescription) {
+        if (selectedFormat.formatType !== 'json') {
+            this.showJsonFormats = [];
+            this.selectJsonFormats = false;
+        }
+
+        this.selectedFormat = selectedFormat;
+        this.selectedFormatEmitter.emit(this.selectedFormat);
+
+    }
+
+    selectJsonFormat() {
+        this.showJsonFormats = this.allJsonFormats;
+        this.selectJsonFormats = true;
+
+        this.selectedFormat = this.allJsonFormats[2];
+        this.selectedFormatEmitter.emit(this.selectedFormat);
 
     }
 
diff --git a/ui/src/app/connect/connect.module.ts b/ui/src/app/connect/connect.module.ts
index fa1a258..0e5e9ea 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -80,6 +80,7 @@ import { SchemaEditorHeaderComponent } from './components/schema-editor/schema-e
 import { StartAdapterConfigurationComponent } from './components/start-adapter-configuration/start-adapter-configuration.component';
 import { DeleteAdapterDialogComponent } from './dialog/delete-adapter-dialog/delete-adapter-dialog.component';
 import { PlatformServicesModule } from '@streampipes/platform-services';
+import { FormatItemJsonComponent } from './components/format-item-json/format-item-json.component';
 
 @NgModule({
   imports: [
@@ -134,7 +135,8 @@ import { PlatformServicesModule } from '@streampipes/platform-services';
     ErrorMessageComponent,
     LoadingMessageComponent,
     SchemaEditorHeaderComponent,
-    StartAdapterConfigurationComponent
+    StartAdapterConfigurationComponent,
+    FormatItemJsonComponent
   ],
   providers: [
     RestService,