Repository: camel Updated Branches: refs/heads/json-simple [created] ae6a9bb9b
CAMEL-10969: Use json-simple as json parser in JSonSchemaHelper instead of our own home-ground parser. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a64bc91d Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a64bc91d Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a64bc91d Branch: refs/heads/json-simple Commit: a64bc91d0f0702632b066091c8361dc6a937a2e6 Parents: c3dcb77 Author: Claus Ibsen <davscl...@apache.org> Authored: Sun Sep 24 10:53:29 2017 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sun Sep 24 11:06:01 2017 +0200 ---------------------------------------------------------------------- camel-core/pom.xml | 12 ++ .../camel/runtimecatalog/JSonSchemaHelper.java | 121 ++++++++----------- platforms/camel-catalog/pom.xml | 36 +++++- .../apache/camel/catalog/JSonSchemaHelper.java | 121 ++++++++----------- 4 files changed, 145 insertions(+), 145 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/a64bc91d/camel-core/pom.xml ---------------------------------------------------------------------- diff --git a/camel-core/pom.xml b/camel-core/pom.xml index 6726527..0029bcc 100644 --- a/camel-core/pom.xml +++ b/camel-core/pom.xml @@ -43,6 +43,7 @@ org.apache.camel.tools.*;resolution:=optional, !org.apache.camel.*, !com.github.benmanes.caffeine.cache, + !org.json.simple, ${camel.osgi.import.defaults}, org.springframework.transaction;resolution:=optional, org.apache.camel.spring.spi;resolution:=optional, @@ -133,6 +134,11 @@ <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> + <dependency> + <groupId>com.github.cliftonlabs</groupId> + <artifactId>json-simple</artifactId> + <version>2.1.2</version> + </dependency> <!-- required dependencies by camel-core --> <dependency> @@ -246,6 +252,7 @@ <plugins> <!-- shade caffeine cache for faster Camel and spi-annotations as needed by everybody --> + <!-- shade json-simple for parsing Camel component JSon schema files --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> @@ -259,6 +266,7 @@ <artifactSet> <includes> <include>com.github.ben-manes.caffeine:caffeine</include> + <include>com.github.cliftonlabs:json-simple</include> <include>org.apache.camel:spi-annotations</include> </includes> <excludes> @@ -270,6 +278,10 @@ <pattern>com.github.benmanes.caffeine</pattern> <shadedPattern>org.apache.camel.com.github.benmanes.caffeine</shadedPattern> </relocation> + <relocation> + <pattern>org.json.simple</pattern> + <shadedPattern>org.apache.camel.org.json.simple</shadedPattern> + </relocation> </relocations> </configuration> </execution> http://git-wip-us.apache.org/repos/asf/camel/blob/a64bc91d/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java index 1e69269..d0e482d 100644 --- a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java +++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java @@ -22,14 +22,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -public final class JSonSchemaHelper { +import org.json.simple.JsonObject; +import org.json.simple.Jsoner; - // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number - private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)"); - private static final String QUOT = """; +public final class JSonSchemaHelper { private JSonSchemaHelper() { } @@ -41,82 +38,62 @@ public final class JSonSchemaHelper { * @param json the json * @return a list of all the rows, where each row is a set of key value pairs with metadata */ + @SuppressWarnings("unchecked") public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) { - List<Map<String, String>> answer = new ArrayList<Map<String, String>>(); + List<Map<String, String>> answer = new ArrayList<>(); if (json == null) { return answer; } - boolean found = false; - - // parse line by line - String[] lines = json.split("\n"); - for (String line : lines) { - // we need to find the group first - if (!found) { - String s = line.trim(); - found = s.startsWith("\"" + group + "\":") && s.endsWith("{"); - continue; - } - - // we should stop when we end the group - if (line.equals(" },") || line.equals(" }")) { - break; - } - - // need to safe encode \" so we can parse the line - line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"'); - - Map<String, String> row = new LinkedHashMap<String, String>(); - Matcher matcher = PATTERN.matcher(line); - - String key; - if (parseProperties) { - // when parsing properties the first key is given as name, so the first parsed token is the value of the name - key = "name"; - } else { - key = null; - } - while (matcher.find()) { - if (key == null) { - key = matcher.group(1); - } else { - String value = matcher.group(1); - if (value != null) { - // its text based - value = value.trim(); - // decode - value = value.replaceAll(QUOT, "\""); - value = decodeJson(value); + // convert into a List<Map<String, String>> structure which is expected as output from this parser + JsonObject output = Jsoner.deserialize(json, new JsonObject()); + for (String key : output.keySet()) { + Map row = output.getMap(key); + if (key.equals(group)) { + if (parseProperties) { + // flattern each entry in the row with name as they key, and its value as the content (its a map also) + for (Object obj : row.entrySet()) { + Map.Entry entry = (Map.Entry) obj; + Map<String, String> newRow = new LinkedHashMap(); + newRow.put("name", entry.getKey().toString()); + + Map newData = transformMap((Map) entry.getValue()); + newRow.putAll(newData); + answer.add(newRow); } - if (value == null) { - // not text then its maybe an enum? - value = matcher.group(2); - if (value != null) { - // its an enum so strip out " and trim spaces after comma - value = value.replaceAll("\"", ""); - value = value.replaceAll(", ", ","); - value = value.trim(); - } - } - if (value == null) { - // not text then its maybe a boolean? - value = matcher.group(3); - } - if (value == null) { - // not text then its maybe a integer? - value = matcher.group(4); - } - if (value != null) { - row.put(key, value); + } else { + // flattern each entry in the row as a list of single Map<key, value> elements + Map newData = transformMap(row); + for (Object obj : newData.entrySet()) { + Map.Entry entry = (Map.Entry) obj; + Map<String, String> newRow = new LinkedHashMap<>(); + newRow.put(entry.getKey().toString(), entry.getValue().toString()); + answer.add(newRow); } - // reset - key = null; } } - if (!row.isEmpty()) { - answer.add(row); + } + + return answer; + } + + private static Map<String, String> transformMap(Map jsonMap) { + Map<String, String> answer = new LinkedHashMap<>(); + + for (Object rowObj : jsonMap.entrySet()) { + Map.Entry rowEntry = (Map.Entry) rowObj; + // if its a list type then its an enum, and we need to parse it as a single line separated with comma + // to be backwards compatible + Object newValue = rowEntry.getValue(); + if (newValue instanceof List) { + List list = (List) newValue; + CollectionStringBuffer csb = new CollectionStringBuffer(","); + for (Object line : list) { + csb.append(line); + } + newValue = csb.toString(); } + answer.put(rowEntry.getKey().toString(), newValue.toString()); } return answer; http://git-wip-us.apache.org/repos/asf/camel/blob/a64bc91d/platforms/camel-catalog/pom.xml ---------------------------------------------------------------------- diff --git a/platforms/camel-catalog/pom.xml b/platforms/camel-catalog/pom.xml index 237a02b..519f868 100644 --- a/platforms/camel-catalog/pom.xml +++ b/platforms/camel-catalog/pom.xml @@ -34,7 +34,13 @@ <dependencies> - <!-- no dependency --> + <!-- required dependencies by camel-catalog --> + <!-- which we shade into camel-catalog so its available for everybody out of the box --> + <dependency> + <groupId>com.github.cliftonlabs</groupId> + <artifactId>json-simple</artifactId> + <version>2.1.2</version> + </dependency> <!-- testing --> <dependency> @@ -162,6 +168,34 @@ </configuration> </plugin> + <!-- shade caffeine cache for faster Camel and spi-annotations as needed by everybody --> + <!-- shade json-simple for parsing Camel component JSon schema files --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <artifactSet> + <includes> + <include>com.github.cliftonlabs:json-simple</include> + </includes> + </artifactSet> + <relocations> + <relocation> + <pattern>org.json.simple</pattern> + <shadedPattern>org.apache.camel.org.json.simple</shadedPattern> + </relocation> + </relocations> + </configuration> + </execution> + </executions> + </plugin> + <!-- generate and include all components in the catalog --> <plugin> <groupId>org.apache.camel</groupId> http://git-wip-us.apache.org/repos/asf/camel/blob/a64bc91d/platforms/camel-catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java ---------------------------------------------------------------------- diff --git a/platforms/camel-catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java b/platforms/camel-catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java index 774facd..bec8e27 100644 --- a/platforms/camel-catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java +++ b/platforms/camel-catalog/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java @@ -22,14 +22,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -public final class JSonSchemaHelper { +import org.json.simple.JsonObject; +import org.json.simple.Jsoner; - // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number - private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)"); - private static final String QUOT = """; +public final class JSonSchemaHelper { private JSonSchemaHelper() { } @@ -41,82 +38,62 @@ public final class JSonSchemaHelper { * @param json the json * @return a list of all the rows, where each row is a set of key value pairs with metadata */ + @SuppressWarnings("unchecked") public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) { - List<Map<String, String>> answer = new ArrayList<Map<String, String>>(); + List<Map<String, String>> answer = new ArrayList<>(); if (json == null) { return answer; } - boolean found = false; - - // parse line by line - String[] lines = json.split("\n"); - for (String line : lines) { - // we need to find the group first - if (!found) { - String s = line.trim(); - found = s.startsWith("\"" + group + "\":") && s.endsWith("{"); - continue; - } - - // we should stop when we end the group - if (line.equals(" },") || line.equals(" }")) { - break; - } - - // need to safe encode \" so we can parse the line - line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"'); - - Map<String, String> row = new LinkedHashMap<String, String>(); - Matcher matcher = PATTERN.matcher(line); - - String key; - if (parseProperties) { - // when parsing properties the first key is given as name, so the first parsed token is the value of the name - key = "name"; - } else { - key = null; - } - while (matcher.find()) { - if (key == null) { - key = matcher.group(1); - } else { - String value = matcher.group(1); - if (value != null) { - // its text based - value = value.trim(); - // decode - value = value.replaceAll(QUOT, "\""); - value = decodeJson(value); + // convert into a List<Map<String, String>> structure which is expected as output from this parser + JsonObject output = Jsoner.deserialize(json, new JsonObject()); + for (String key : output.keySet()) { + Map row = output.getMap(key); + if (key.equals(group)) { + if (parseProperties) { + // flattern each entry in the row with name as they key, and its value as the content (its a map also) + for (Object obj : row.entrySet()) { + Map.Entry entry = (Map.Entry) obj; + Map<String, String> newRow = new LinkedHashMap(); + newRow.put("name", entry.getKey().toString()); + + Map newData = transformMap((Map) entry.getValue()); + newRow.putAll(newData); + answer.add(newRow); } - if (value == null) { - // not text then its maybe an enum? - value = matcher.group(2); - if (value != null) { - // its an enum so strip out " and trim spaces after comma - value = value.replaceAll("\"", ""); - value = value.replaceAll(", ", ","); - value = value.trim(); - } - } - if (value == null) { - // not text then its maybe a boolean? - value = matcher.group(3); - } - if (value == null) { - // not text then its maybe a integer? - value = matcher.group(4); - } - if (value != null) { - row.put(key, value); + } else { + // flattern each entry in the row as a list of single Map<key, value> elements + Map newData = transformMap(row); + for (Object obj : newData.entrySet()) { + Map.Entry entry = (Map.Entry) obj; + Map<String, String> newRow = new LinkedHashMap<>(); + newRow.put(entry.getKey().toString(), entry.getValue().toString()); + answer.add(newRow); } - // reset - key = null; } } - if (!row.isEmpty()) { - answer.add(row); + } + + return answer; + } + + private static Map<String, String> transformMap(Map jsonMap) { + Map<String, String> answer = new LinkedHashMap<>(); + + for (Object rowObj : jsonMap.entrySet()) { + Map.Entry rowEntry = (Map.Entry) rowObj; + // if its a list type then its an enum, and we need to parse it as a single line separated with comma + // to be backwards compatible + Object newValue = rowEntry.getValue(); + if (newValue instanceof List) { + List list = (List) newValue; + CollectionStringBuffer csb = new CollectionStringBuffer(","); + for (Object line : list) { + csb.append(line); + } + newValue = csb.toString(); } + answer.put(rowEntry.getKey().toString(), newValue.toString()); } return answer;