View Issue Details

IDProjectCategoryView StatusLast Update
0000017KafkaEsqueImprovementpublic2018-12-16 12:23
ReporterEminAssigned Topatschuh 
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Product Version0.12.0 
Target VersionFixed in Version 
Summary0000017: Json Tree View Patch
Description

Patch for Json Tree View when using Format as Json.

Needs work to deal with nested ArrayLists/Maps and to clean up unsafe casts.

TagsNo tags attached.

Activities

Emin

Emin

2018-12-14 08:26

reporter  

jsontree.patch (4,129 bytes)
Index: src/main/java/com/modulo/kafkaesque/Controller.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/com/modulo/kafkaesque/Controller.java	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/java/com/modulo/kafkaesque/Controller.java	(date 1544743259000)
@@ -1,6 +1,7 @@
 package com.modulo.kafkaesque;
 
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 import com.google.inject.Inject;
@@ -99,6 +100,8 @@
     private TextArea keyTextArea;
     @FXML
     private TextArea valueTextArea;
+    @FXML
+    public TreeView<String> jsonTreeView;
     @FXML
     private TableView<Header> headerTableView;
     @FXML
@@ -252,12 +255,48 @@
         if (formatJson) {
             keyTextArea.setText(formatJson(selectedMessage.getKey()));
             valueTextArea.setText(formatJson(selectedMessage.getValue()));
+            try {
+                Map<String, Object> json = objectMapper.readValue(selectedMessage.getValue(), Map.class);
+                TreeItem<String> root = new TreeItem<>("root");
+                recursivelyAddElements(json, root);
+                jsonTreeView.setRoot(root);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
         } else {
             keyTextArea.setText(selectedMessage.getKey());
             valueTextArea.setText(selectedMessage.getValue());
         }
     }
 
+    private void recursivelyAddElements(Map<String, Object> jsonNode, TreeItem<String> treeItem) {
+        Set<Map.Entry<String, Object>> entries = jsonNode.entrySet();
+
+        if (!entries.isEmpty()) {
+            for (Map.Entry<String, Object> entry : entries) {
+                TreeItem<String> newItem = new TreeItem<>(entry.getKey());
+                treeItem.getChildren().add(newItem);
+                if (entry.getValue() instanceof String) {
+                    recursivelyAddElements((String) entry.getValue(), newItem);
+                } else if (entry.getValue() instanceof ArrayList) {
+                    recursivelyAddElements((ArrayList) entry.getValue(), newItem);
+                } else {
+                    recursivelyAddElements((Map<String, Object>) entry.getValue(), newItem);
+                }
+            }
+        }
+    }
+
+    private void recursivelyAddElements(ArrayList values, TreeItem<String> treeItem) {
+        for (Object val : values){
+            treeItem.getChildren().add(new TreeItem<>((String) val));
+        }
+    }
+
+    private void recursivelyAddElements(String string, TreeItem<String> treeItem) {
+        treeItem.getChildren().add(new TreeItem<>(string));
+    }
+
     /* TODO can be extracted to a JsonUtil */
     private String formatJson(String string) {
         try {
Index: src/main/resources/fxml/mainScene.fxml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/resources/fxml/mainScene.fxml	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/resources/fxml/mainScene.fxml	(date 1544743450000)
@@ -223,7 +223,11 @@
                         </Tab>
                         <Tab text="Value">
                             <content>
-                                <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0" prefWidth="200.0"/>
+                                <HBox>
+                                    <TreeView fx:id="jsonTreeView" editable="false" prefHeight="200.0"/>
+                                    <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0"
+                                              prefWidth="200.0" HBox.hgrow="ALWAYS"/>
+                                </HBox>
                             </content>
                         </Tab>
                         <Tab text="Header">
jsontree.patch (4,129 bytes)
Emin

Emin

2018-12-14 11:49

reporter   ~0000018

New Patch with infinitely recursive search and support for non-string types



jsontree-new.patch (4,432 bytes)
Index: src/main/resources/fxml/mainScene.fxml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/resources/fxml/mainScene.fxml	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/resources/fxml/mainScene.fxml	(date 1544774332456)
@@ -223,7 +223,11 @@
                         </Tab>
                         <Tab text="Value">
                             <content>
-                                <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0" prefWidth="200.0"/>
+                                <HBox>
+                                    <TreeView fx:id="jsonTreeView" editable="false" prefHeight="200.0"/>
+                                    <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0"
+                                              prefWidth="200.0" HBox.hgrow="ALWAYS"/>
+                                </HBox>
                             </content>
                         </Tab>
                         <Tab text="Header">
Index: src/main/java/com/modulo/kafkaesque/Controller.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/com/modulo/kafkaesque/Controller.java	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/java/com/modulo/kafkaesque/Controller.java	(date 1544785811155)
@@ -100,6 +100,8 @@
     @FXML
     private TextArea valueTextArea;
     @FXML
+    public TreeView<String> jsonTreeView;
+    @FXML
     private TableView<Header> headerTableView;
     @FXML
     private TableColumn<Header, String> headerKeyColumn;
@@ -252,12 +254,57 @@
         if (formatJson) {
             keyTextArea.setText(formatJson(selectedMessage.getKey()));
             valueTextArea.setText(formatJson(selectedMessage.getValue()));
+            try {
+                Map<String, Object> json = objectMapper.readValue(selectedMessage.getValue(), Map.class);
+                TreeItem<String> root = new TreeItem<>("root");
+                recursivelyAddElements(json, root);
+                jsonTreeView.setRoot(root);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
         } else {
             keyTextArea.setText(selectedMessage.getKey());
             valueTextArea.setText(selectedMessage.getValue());
         }
     }
 
+    private void recursivelyAddElements(Map<String, Object> jsonNode, TreeItem<String> treeItem) {
+        Set<Map.Entry<String, Object>> entries = jsonNode.entrySet();
+
+        if (!entries.isEmpty()) {
+            for (Map.Entry<String, Object> entry : entries) {
+                TreeItem<String> newItem = new TreeItem<>(entry.getKey());
+                treeItem.getChildren().add(newItem);
+                applyCorrectAdder(entry.getValue(), newItem);
+            }
+        }
+    }
+
+    private void recursivelyAddElements(ArrayList values, TreeItem<String> treeItem) {
+        int i = 1;
+        for (Object val : values) {
+            TreeItem<String> newItem = new TreeItem<>(i + "");
+            treeItem.getChildren().add(newItem);
+            applyCorrectAdder(val, newItem);
+            i++;
+        }
+    }
+
+    private void recursivelyAddElements(String val, TreeItem<String> treeItem) {
+        treeItem.getChildren().add(new TreeItem<>(val));
+    }
+
+    private void applyCorrectAdder(Object value, TreeItem<String> treeItem) {
+        if (value instanceof Map) {
+            recursivelyAddElements((Map) value, treeItem);
+        }else if (value instanceof ArrayList) {
+            recursivelyAddElements((ArrayList) value, treeItem);
+        } else {
+            recursivelyAddElements((String.valueOf(value)), treeItem);
+        }
+    }
+
+
     /* TODO can be extracted to a JsonUtil */
     private String formatJson(String string) {
         try {
@@ -952,7 +999,7 @@
             String identifier = matcher.group("identifier");
             String type = matcher.group("type");
 
-            Object replacement;
+            Serializable replacement;
             switch (type) {
                 case "UUID":
                     replacement = UUID.randomUUID();
jsontree-new.patch (4,432 bytes)
Emin

Emin

2018-12-14 12:21

reporter   ~0000019

Final Patch with code cleanup and auto expansion of lists and top level map



jsontree-final.patch (7,510 bytes)
Index: src/main/resources/fxml/mainScene.fxml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/resources/fxml/mainScene.fxml	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/resources/fxml/mainScene.fxml	(date 1544789099034)
@@ -223,7 +223,11 @@
                         </Tab>
                         <Tab text="Value">
                             <content>
-                                <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0" prefWidth="200.0"/>
+                                <HBox>
+                                    <TreeView fx:id="jsonTreeView" prefHeight="200.0" prefWidth="400.0"/>
+                                    <TextArea fx:id="valueTextArea" editable="false" prefHeight="200.0"
+                                              prefWidth="200.0" HBox.hgrow="ALWAYS"/>
+                                </HBox>
                             </content>
                         </Tab>
                         <Tab text="Header">
Index: src/main/java/com/modulo/kafkaesque/Controller.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/com/modulo/kafkaesque/Controller.java	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/java/com/modulo/kafkaesque/Controller.java	(date 1544789994257)
@@ -100,6 +100,8 @@
     @FXML
     private TextArea valueTextArea;
     @FXML
+    public TreeView<String> jsonTreeView;
+    @FXML
     private TableView<Header> headerTableView;
     @FXML
     private TableColumn<Header, String> headerKeyColumn;
@@ -250,24 +252,20 @@
         }
         headerTableView.setItems(selectedMessage.getHeaders());
         if (formatJson) {
-            keyTextArea.setText(formatJson(selectedMessage.getKey()));
-            valueTextArea.setText(formatJson(selectedMessage.getValue()));
+            keyTextArea.setText(JsonUtils.formatJson(selectedMessage.getKey()));
+            valueTextArea.setText(JsonUtils.formatJson(selectedMessage.getValue()));
+            try {
+                TreeItem<String> root = JsonUtils.buildTreeFromJson(selectedMessage.getValue());
+                jsonTreeView.setRoot(root);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
         } else {
             keyTextArea.setText(selectedMessage.getKey());
             valueTextArea.setText(selectedMessage.getValue());
         }
     }
 
-    /* TODO can be extracted to a JsonUtil */
-    private String formatJson(String string) {
-        try {
-            Object jsonObject = string == null ? null : objectMapper.readValue(string, Object.class);
-            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
-        } catch (Exception e) {
-            return String.format("%s%s[Formatting Error: %s]", string, System.lineSeparator(), e.getMessage());
-        }
-    }
-
     private void setupClusterCombobox() {
         ListCell<ClusterConfig> buttonCell = new ListCell<ClusterConfig>() {
             @Override
@@ -952,7 +950,7 @@
             String identifier = matcher.group("identifier");
             String type = matcher.group("type");
 
-            Object replacement;
+            Serializable replacement;
             switch (type) {
                 case "UUID":
                     replacement = UUID.randomUUID();
Index: src/main/java/com/modulo/kafkaesque/JsonUtils.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/com/modulo/kafkaesque/JsonUtils.java	(revision dbc9c10b8a607e7ff939f603db97dae122bcc29b)
+++ src/main/java/com/modulo/kafkaesque/JsonUtils.java	(date 1544789963178)
@@ -1,24 +1,89 @@
 package com.modulo.kafkaesque;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import javafx.scene.control.TreeItem;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Set;
 
-public final class JsonUtils {
+final class JsonUtils {
     private JsonUtils() {
     }
 
-    public static ValidationResult validate(String jsonInString) {
+    private static final ObjectMapper objectMapper;
+
+    static {
+        objectMapper = new ObjectMapper();
+    }
+
+    static String formatJson(String string) {
+        try {
+            Object jsonObject = string == null ? null : objectMapper.readValue(string, Object.class);
+            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
+        } catch (Exception e) {
+            return String.format("%s%s[Formatting Error: %s]", string, System.lineSeparator(), e.getMessage());
+        }
+    }
+
+    static ValidationResult validate(String jsonInString) {
         if (jsonInString == null) {
             return new ValidationResult(true);
         }
 
         try {
-            final ObjectMapper mapper = new ObjectMapper();
-            mapper.readTree(jsonInString);
+            objectMapper.readTree(jsonInString);
             return new ValidationResult(true);
         } catch (IOException e) {
             return new ValidationResult(false, e.getMessage());
         }
     }
+
+    static TreeItem<String> buildTreeFromJson(String value) throws IOException {
+        Map<String, Object> json = objectMapper.readValue(value, new TypeReference<Map<String, Object>>() {
+        });
+        TreeItem<String> root = new TreeItem<>("root");
+        root.setExpanded(true);
+        recursivelyAddElements(json, root);
+        return root;
+    }
+
+    private static void recursivelyAddElements(Map<String, Object> jsonNode, TreeItem<String> treeItem) {
+        Set<Map.Entry<String, Object>> entries = jsonNode.entrySet();
+
+        if (!entries.isEmpty()) {
+            for (Map.Entry<String, Object> entry : entries) {
+                TreeItem<String> newItem = new TreeItem<>(entry.getKey());
+                treeItem.getChildren().add(newItem);
+                applyCorrectAdder(entry.getValue(), newItem);
+            }
+        }
+    }
+
+    private static void recursivelyAddElements(ArrayList values, TreeItem<String> treeItem) {
+        int i = 1;
+        for (Object val : values) {
+            TreeItem<String> newItem = new TreeItem<>(i + "");
+            treeItem.getChildren().add(newItem);
+            treeItem.setExpanded(true);
+            applyCorrectAdder(val, newItem);
+            i++;
+        }
+    }
+
+    private static void recursivelyAddElements(String val, TreeItem<String> treeItem) {
+        treeItem.setValue(treeItem.getValue() + ": " + val);
+    }
+
+    private static void applyCorrectAdder(Object value, TreeItem<String> treeItem) {
+        if (value instanceof Map) {
+            recursivelyAddElements((Map<String, Object>) value, treeItem);
+        } else if (value instanceof ArrayList) {
+            recursivelyAddElements((ArrayList) value, treeItem);
+        } else {
+            recursivelyAddElements((String.valueOf(value)), treeItem);
+        }
+    }
 }
jsontree-final.patch (7,510 bytes)
patschuh

patschuh

2018-12-16 12:23

developer   ~0000020

Implemented the JsonTreeView as its own control based on the patch

Related Changesets

KafkaEsque: master 0303f2f6

2018-12-16 12:20:03

patschuh

Details Diff
[ESQUE-17]: Added JsonTreeView control
Affected Issues
0000017

Issue History

Date Modified Username Field Change
2018-12-14 08:26 Emin New Issue
2018-12-14 08:26 Emin File Added: jsontree.patch
2018-12-14 11:49 Emin File Added: jsontree-new.patch
2018-12-14 11:49 Emin Note Added: 0000018
2018-12-14 12:21 Emin File Added: jsontree-final.patch
2018-12-14 12:21 Emin Note Added: 0000019
2018-12-16 12:20 patschuh Changeset attached => KafkaEsque master 0303f2f6
2018-12-16 12:23 patschuh Assigned To => patschuh
2018-12-16 12:23 patschuh Status new => resolved
2018-12-16 12:23 patschuh Resolution open => fixed
2018-12-16 12:23 patschuh Note Added: 0000020