You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/07/19 15:08:22 UTC

camel git commit: CAMEL-11558: Add writeAsString option to camel-jsonpath so you can easily split a json document into a list of string values

Repository: camel
Updated Branches:
  refs/heads/master 4cdb8f573 -> 5aa5ef9ba


CAMEL-11558: Add writeAsString option to camel-jsonpath so you can easily split a json document into a list of string values


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/5aa5ef9b
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/5aa5ef9b
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/5aa5ef9b

Branch: refs/heads/master
Commit: 5aa5ef9ba796f624a1d8f8da94eaaa3bc4777bb8
Parents: 4cdb8f5
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Jul 19 16:55:58 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Jul 19 17:08:05 2017 +0200

----------------------------------------------------------------------
 .../apache/camel/builder/ExpressionClause.java  | 25 ++++++
 .../camel/builder/ExpressionClauseSupport.java  | 43 +++++++++
 .../model/language/JsonPathExpression.java      | 19 ++++
 .../src/main/docs/jsonpath-language.adoc        | 31 ++++++-
 .../apache/camel/jsonpath/JsonPathAdapter.java  |  9 ++
 .../apache/camel/jsonpath/JsonPathEngine.java   | 91 ++++++++++++++++----
 .../camel/jsonpath/JsonPathExpression.java      | 14 ++-
 .../jsonpath/jackson/JacksonJsonAdapter.java    | 12 +++
 .../camel/jsonpath/JsonPathSplitTest.java       | 65 ++++++++++++++
 .../JsonPathSplitWriteAsStringMapTest.java      | 62 +++++++++++++
 .../JsonPathSplitWriteAsStringTest.java         | 56 ++++++++++++
 .../SpringJsonPathSplitWriteAsStringTest.java   | 47 ++++++++++
 .../src/test/resources/content-map.json         | 14 +++
 .../src/test/resources/content.json             | 14 +++
 .../SpringJsonPathSplitWriteAsStringTest.xml    | 37 ++++++++
 .../JsonPathLanguageConfiguration.java          | 13 +++
 16 files changed, 533 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
index 05fd859..9a95020 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
@@ -497,6 +497,31 @@ public class ExpressionClause<T> extends ExpressionDefinition {
     }
 
     /**
+     * Evaluates a <a
+     * href="http://camel.apache.org/jsonpath.html">Json Path
+     * expression</a> with writeAsString enabled.
+     *
+     * @param text the expression to be evaluated
+     * @return the builder to continue processing the DSL
+     */
+    public T jsonpathWriteAsString(String text) {
+        return delegate.jsonpathWriteAsString(text);
+    }
+
+    /**
+     * Evaluates a <a
+     * href="http://camel.apache.org/jsonpath.html">Json Path
+     * expression</a> with writeAsString enabled.
+     *
+     * @param text the expression to be evaluated
+     * @param suppressExceptions whether to suppress exceptions such as PathNotFoundException
+     * @return the builder to continue processing the DSL
+     */
+    public T jsonpathWriteAsString(String text, boolean suppressExceptions) {
+        return delegate.jsonpathWriteAsString(text, suppressExceptions);
+    }
+
+    /**
      * Evaluates a <a href="http://commons.apache.org/jxpath/">JXPath expression</a>
      * 
      * @param text the expression to be evaluated

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
index 64cef85..c1e487a 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
@@ -428,6 +428,49 @@ public class ExpressionClauseSupport<T> {
     }
 
     /**
+     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
+     * expression</a> with writeAsString enabled.
+     *
+     * @param text the expression to be evaluated
+     * @return the builder to continue processing the DSL
+     */
+    public T jsonpathWriteAsString(String text) {
+        return jsonpathWriteAsString(text, false);
+    }
+
+    /**
+     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
+     * expression</a> with writeAsString enabled.
+     *
+     * @param text the expression to be evaluated
+     * @param suppressExceptions whether to suppress exceptions such as PathNotFoundException
+     * @return the builder to continue processing the DSL
+     */
+    public T jsonpathWriteAsString(String text, boolean suppressExceptions) {
+        JsonPathExpression expression = new JsonPathExpression(text);
+        expression.setWriteAsString(true);
+        expression.setSuppressExceptions(suppressExceptions);
+        return expression(expression);
+    }
+
+    /**
+     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
+     * expression</a> with writeAsString enabled.
+     *
+     * @param text the expression to be evaluated
+     * @param suppressExceptions whether to suppress exceptions such as PathNotFoundException
+     * @param allowSimple whether to allow in inlined simple exceptions in the json path expression
+     * @return the builder to continue processing the DSL
+     */
+    public T jsonpathWriteAsString(String text, boolean suppressExceptions, boolean allowSimple) {
+        JsonPathExpression expression = new JsonPathExpression(text);
+        expression.setWriteAsString(true);
+        expression.setSuppressExceptions(suppressExceptions);
+        expression.setAllowSimple(allowSimple);
+        return expression(expression);
+    }
+
+    /**
      * Evaluates a <a href="http://commons.apache.org/jxpath/">JXPath expression</a>
      *
      * @param text the expression to be evaluated

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/camel-core/src/main/java/org/apache/camel/model/language/JsonPathExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/language/JsonPathExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/JsonPathExpression.java
index 0fc3ae4..574b752 100644
--- a/camel-core/src/main/java/org/apache/camel/model/language/JsonPathExpression.java
+++ b/camel-core/src/main/java/org/apache/camel/model/language/JsonPathExpression.java
@@ -48,6 +48,8 @@ public class JsonPathExpression extends ExpressionDefinition {
     private Boolean allowSimple;
     @XmlAttribute @Metadata(defaultValue = "true")
     private Boolean allowEasyPredicate;
+    @XmlAttribute @Metadata(defaultValue = "false")
+    private Boolean writeAsString;
 
     public JsonPathExpression() {
     }
@@ -111,6 +113,17 @@ public class JsonPathExpression extends ExpressionDefinition {
         this.suppressExceptions = suppressExceptions;
     }
 
+    public Boolean getWriteAsString() {
+        return writeAsString;
+    }
+
+    /**
+     * Whether to write the output of each row/element as a JSon String value instead of a Map/POJO value.
+     */
+    public void setWriteAsString(Boolean writeAsString) {
+        this.writeAsString = writeAsString;
+    }
+
     public String getLanguage() {
         return "jsonpath";
     }
@@ -141,6 +154,9 @@ public class JsonPathExpression extends ExpressionDefinition {
         if (allowEasyPredicate != null) {
             setProperty(expression, "allowEasyPredicate", allowEasyPredicate);
         }
+        if (writeAsString != null) {
+            setProperty(expression, "writeAsString", writeAsString);
+        }
         super.configureExpression(camelContext, expression);
     }
 
@@ -158,6 +174,9 @@ public class JsonPathExpression extends ExpressionDefinition {
         if (allowEasyPredicate != null) {
             setProperty(predicate, "allowEasyPredicate", allowEasyPredicate);
         }
+        if (writeAsString != null) {
+            setProperty(predicate, "writeAsString", writeAsString);
+        }
         super.configurePredicate(camelContext, predicate);
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc
index c265ef7..fa22336 100644
--- a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc
+++ b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc
@@ -22,7 +22,7 @@ from("queue:books.new")
 
 
 // language options: START
-The JSonPath language supports 5 options which are listed below.
+The JSonPath language supports 6 options which are listed below.
 
 
 
@@ -33,6 +33,7 @@ The JSonPath language supports 5 options which are listed below.
 | suppressExceptions | false | Boolean | Whether to suppress exceptions such as PathNotFoundException.
 | allowSimple | true | Boolean | Whether to allow in inlined simple exceptions in the json path expression
 | allowEasyPredicate | true | Boolean | Whether to allow using the easy predicate parser to pre-parse predicates.
+| writeAsString | false | Boolean | Whether to write the output of each row/element as a JSon String value instead of a Map/POJO value.
 | trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks
 |=======================================================================
 // language options: END
@@ -254,6 +255,34 @@ you enter the document in String format to the JSONPath component or you
 can specify the encoding in the headerĀ "*CamelJsonPathJsonEncoding*"
 (JsonpathConstants.HEADER_JSON_ENCODING).
 
+### Split JSon data into sub rows as JSon
+
+You can use jsonpath to split a JSon document, such as:
+
+[source,java]
+---------------------------------------------------------------------------------------------------
+    from("direct:start")
+        .split().jsonpath("$.store.book[*]")
+        .to("log:book");
+---------------------------------------------------------------------------------------------------
+
+Then each book is logged, however the message body is a `Map` instance. Sometimes
+you may want to output this as plain String JSon value instead, which can be done
+from *Camel 2.20* onwards with the `writeAsString` option as shown:
+
+[source,java]
+---------------------------------------------------------------------------------------------------
+    from("direct:start")
+        .split().jsonpathWriteAsString("$.store.book[*]")
+        .to("log:book");
+---------------------------------------------------------------------------------------------------
+
+Then each book is logged as a String JSon value. For earlier versions of Camel you
+would need to use camel-jackson dataformat and marshal the message body to make it
+convert the message body from `Map` to a `String` type.
+
+
+
 ### Dependencies
 
 To use JSonPath in your camel routes you need to add the a dependency on

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAdapter.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAdapter.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAdapter.java
index bcba3da..a6c1e9d 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAdapter.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAdapter.java
@@ -38,4 +38,13 @@ public interface JsonPathAdapter {
      * @return converted as {@link Map} or <tt>null</tt> if not possible
      */
     Map readValue(Object body, Exchange exchange);
+
+    /**
+     * Attempts to write the value as a JSOn {@link String} value.
+     *
+     * @param value  the value
+     * @param exchange the Camel exchange
+     * @return written as {@link String} JSon or <tt>null</tt> if not possible
+     */
+    String writeAsString(Object value, Exchange exchange);
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
index 8224bd2..d6d506c 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -50,17 +51,19 @@ public class JsonPathEngine {
 
     private static final Pattern SIMPLE_PATTERN = Pattern.compile("\\$\\{[^\\}]+\\}", Pattern.MULTILINE);
     private final String expression;
+    private final boolean writeAsString;
     private final JsonPath path;
     private final Configuration configuration;
     private JsonPathAdapter adapter;
     private volatile boolean initJsonAdapter;
 
     public JsonPathEngine(String expression) {
-        this(expression, false, true, null);
+        this(expression, false, false, true, null);
     }
 
-    public JsonPathEngine(String expression, boolean suppressExceptions, boolean allowSimple, Option[] options) {
+    public JsonPathEngine(String expression, boolean writeAsString, boolean suppressExceptions, boolean allowSimple, Option[] options) {
         this.expression = expression;
+        this.writeAsString = writeAsString;
 
         Defaults defaults = DefaultsImpl.INSTANCE;
         if (options != null) {
@@ -94,15 +97,65 @@ public class JsonPathEngine {
     }
 
     public Object read(Exchange exchange) throws Exception {
+        Object answer;
         if (path == null) {
             Expression exp = exchange.getContext().resolveLanguage("simple").createExpression(expression);
             String text = exp.evaluate(exchange, String.class);
             JsonPath path = JsonPath.compile(text);
             LOG.debug("Compiled dynamic JsonPath: {}", expression);
-            return doRead(path, exchange);
+            answer = doRead(path, exchange);
         } else {
-            return doRead(path, exchange);
+            answer = doRead(path, exchange);
         }
+
+        if (writeAsString) {
+
+            if (!initJsonAdapter) {
+                doInitAdapter(exchange);
+            }
+
+            if (adapter == null) {
+                LOG.debug("Cannot writeAsString as adapter cannot be initialized");
+                // return as-is as there is no adapter
+                return answer;
+            }
+
+            // write each row as a string but keep it as a list/iterable
+            if (answer instanceof Iterable) {
+                List<String> list = new ArrayList<>();
+                Iterable it = (Iterable) answer;
+                for (Object o : it) {
+                    if (adapter != null) {
+                        String json = adapter.writeAsString(o, exchange);
+                        if (json != null) {
+                            list.add(json);
+                        }
+                    }
+                }
+                return list;
+            } else if (answer instanceof Map) {
+                Map map = (Map) answer;
+                for (Object key : map.keySet()) {
+                    Object value = map.get(key);
+                    if (adapter != null) {
+                        String json = adapter.writeAsString(value, exchange);
+                        if (json != null) {
+                            map.put(key, json);
+                        }
+                    }
+                }
+                return map;
+            } else {
+                if (adapter != null) {
+                    String json = adapter.writeAsString(answer, exchange);
+                    if (json != null) {
+                        return json;
+                    }
+                }
+            }
+        }
+
+        return answer;
     }
 
     private Object doRead(JsonPath path, Exchange exchange) throws IOException, CamelExchangeException {
@@ -182,6 +235,23 @@ public class JsonPathEngine {
         Object json = exchange.getIn().getBody();
         LOG.trace("JSonPath: {} is read with adapter from message body: {}", path, json);
 
+        doInitAdapter(exchange);
+
+        if (adapter != null) {
+            LOG.trace("Attempting to use JacksonJsonAdapter: {}", adapter);
+            Map map = adapter.readValue(json, exchange);
+            if (map != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("JacksonJsonAdapter converted message body from: {} to: java.util.Map", ObjectHelper.classCanonicalName(json));
+                }
+                return path.read(map, configuration);
+            }
+        }
+
+        return null;
+    }
+
+    private void doInitAdapter(Exchange exchange) {
         if (!initJsonAdapter) {
             try {
                 // need to load this adapter dynamically as its optional
@@ -200,18 +270,5 @@ public class JsonPathEngine {
             }
             initJsonAdapter = true;
         }
-
-        if (adapter != null) {
-            LOG.trace("Attempting to use JacksonJsonAdapter: {}", adapter);
-            Map map = adapter.readValue(json, exchange);
-            if (map != null) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("JacksonJsonAdapter converted message body from: {} to: java.util.Map", ObjectHelper.classCanonicalName(json));
-                }
-                return path.read(map, configuration);
-            }
-        }
-
-        return null;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
index 3e46a98..c5bf74f 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
@@ -39,6 +39,7 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
     private boolean suppressExceptions;
     private boolean allowSimple = true;
     private boolean allowEasyPredicate = true;
+    private boolean writeAsString;
     private Option[] options;
 
     public JsonPathExpression(String expression) {
@@ -101,6 +102,17 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
         this.allowEasyPredicate = allowEasyPredicate;
     }
 
+    public boolean isWriteAsString() {
+        return writeAsString;
+    }
+
+    /**
+     * Whether to write the output of each row/element as a JSon String value instead of a Map/POJO value.
+     */
+    public void setWriteAsString(boolean writeAsString) {
+        this.writeAsString = writeAsString;
+    }
+
     public Option[] getOptions() {
         return options;
     }
@@ -145,7 +157,7 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
 
         LOG.debug("Initializing {} using: {}", predicate ? "predicate" : "expression", exp);
         try {
-            engine = new JsonPathEngine(exp, suppressExceptions, allowSimple, options);
+            engine = new JsonPathEngine(exp, writeAsString, suppressExceptions, allowSimple, options);
         } catch (Exception e) {
             throw new ExpressionIllegalSyntaxException(exp, e);
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/jackson/JacksonJsonAdapter.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/jackson/JacksonJsonAdapter.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/jackson/JacksonJsonAdapter.java
index 0cb5837..690a42d 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/jackson/JacksonJsonAdapter.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/jackson/JacksonJsonAdapter.java
@@ -68,6 +68,18 @@ public class JacksonJsonAdapter implements JsonPathAdapter {
         return null;
     }
 
+    @Override
+    public String writeAsString(Object value, Exchange exchange) {
+        ObjectMapper mapper = resolveObjectMapper(exchange.getContext().getRegistry());
+        try {
+            return mapper.writeValueAsString(value);
+        } catch (Throwable e) {
+            // ignore because we are attempting to convert
+        }
+
+        return null;
+    }
+
     private ObjectMapper resolveObjectMapper(Registry registry) {
         Set<ObjectMapper> mappers = registry.findByType(ObjectMapper.class);
         if (mappers.size() == 1) {

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitTest.java
new file mode 100644
index 0000000..a0ce136
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitTest.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+package org.apache.camel.jsonpath;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class JsonPathSplitTest extends CamelTestSupport {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .split().jsonpath("$.store.book[*]")
+                    .to("mock:authors")
+                    .convertBodyTo(String.class);
+            }
+        };
+    }
+
+    @Test
+    public void testSplit() throws Exception {
+        getMockEndpoint("mock:authors").expectedMessageCount(2);
+
+        String out = template.requestBody("direct:start", new File("src/test/resources/books.json"), String.class);
+        assertNotNull(out);
+
+        assertMockEndpointsSatisfied();
+
+        Map row = getMockEndpoint("mock:authors").getReceivedExchanges().get(0).getIn().getBody(Map.class);
+        assertEquals("Nigel Rees", row.get("author"));
+        assertEquals(Double.valueOf("8.95"), row.get("price"));
+
+        row = getMockEndpoint("mock:authors").getReceivedExchanges().get(1).getIn().getBody(Map.class);
+        assertEquals("Evelyn Waugh", row.get("author"));
+        assertEquals(Double.valueOf("12.99"), row.get("price"));
+
+        // should preserve quotes etc
+        assertTrue(out.contains("\"author\": \"Nigel Rees\""));
+        assertTrue(out.contains("\"price\": 8.95"));
+        assertTrue(out.contains("\"title\": \"Sword of Honour\""));
+        assertTrue(out.contains("\"price\": 12.99,"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringMapTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringMapTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringMapTest.java
new file mode 100644
index 0000000..689ea00
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringMapTest.java
@@ -0,0 +1,62 @@
+/**
+ * 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.
+ */
+package org.apache.camel.jsonpath;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class JsonPathSplitWriteAsStringMapTest extends CamelTestSupport {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .split().jsonpathWriteAsString("$.content")
+                        .to("mock:line")
+                        .to("log:line")
+                    .end();
+            }
+        };
+    }
+
+    @Test
+    public void testSplitToJSon() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:line");
+        // we only get 1 map (because we split via: $.content) but each entry is converted to a json string
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", new File("src/test/resources/content-map.json"));
+
+        assertMockEndpointsSatisfied();
+
+        Map map = mock.getReceivedExchanges().get(0).getIn().getBody(Map.class);
+
+        String foo = (String) map.get("foo");
+        assertEquals("{\"action\":\"CU\",\"id\":123,\"modifiedTime\":\"2015-07-28T11:40:09.520+02:00\"}", foo);
+
+        String bar = (String) map.get("bar");
+        assertEquals("{\"action\":\"CU\",\"id\":456,\"modifiedTime\":\"2015-07-28T11:42:29.510+02:00\"}", bar);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringTest.java
new file mode 100644
index 0000000..d0f0810
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSplitWriteAsStringTest.java
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+package org.apache.camel.jsonpath;
+
+import java.io.File;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class JsonPathSplitWriteAsStringTest extends CamelTestSupport {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .split().jsonpathWriteAsString("$.content")
+                        .to("mock:line")
+                        .to("log:line")
+                    .end();
+            }
+        };
+    }
+
+    @Test
+    public void testSplitToJSon() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:line");
+        mock.expectedMessageCount(2);
+        // we want the output as JSon string
+        mock.allMessages().body().isInstanceOf(String.class);
+        mock.message(0).body().isEqualTo("{\"action\":\"CU\",\"id\":123,\"modifiedTime\":\"2015-07-28T11:40:09.520+02:00\"}");
+        mock.message(1).body().isEqualTo("{\"action\":\"CU\",\"id\":456,\"modifiedTime\":\"2015-07-28T11:42:29.510+02:00\"}");
+
+        template.sendBody("direct:start", new File("src/test/resources/content.json"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.java
new file mode 100644
index 0000000..b4a0d41
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.java
@@ -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.
+ */
+package org.apache.camel.jsonpath;
+
+import java.io.File;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringJsonPathSplitWriteAsStringTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.xml");
+    }
+
+    @Test
+    public void testSplitToJSon() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:line");
+        mock.expectedMessageCount(2);
+        // we want the output as JSon string
+        mock.allMessages().body().isInstanceOf(String.class);
+        mock.message(0).body().isEqualTo("{\"action\":\"CU\",\"id\":123,\"modifiedTime\":\"2015-07-28T11:40:09.520+02:00\"}");
+        mock.message(1).body().isEqualTo("{\"action\":\"CU\",\"id\":456,\"modifiedTime\":\"2015-07-28T11:42:29.510+02:00\"}");
+
+        template.sendBody("direct:start", new File("src/test/resources/content.json"));
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/resources/content-map.json
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/resources/content-map.json b/components/camel-jsonpath/src/test/resources/content-map.json
new file mode 100644
index 0000000..a3ac667
--- /dev/null
+++ b/components/camel-jsonpath/src/test/resources/content-map.json
@@ -0,0 +1,14 @@
+{
+  "content": {
+    "foo": {
+      "action": "CU",
+      "id": 123,
+      "modifiedTime": "2015-07-28T11:40:09.520+02:00"
+    },
+    "bar": {
+      "action": "CU",
+      "id": 456,
+      "modifiedTime": "2015-07-28T11:42:29.510+02:00"
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/resources/content.json
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/resources/content.json b/components/camel-jsonpath/src/test/resources/content.json
new file mode 100644
index 0000000..94d2572
--- /dev/null
+++ b/components/camel-jsonpath/src/test/resources/content.json
@@ -0,0 +1,14 @@
+{
+  "content": [
+    {
+      "action": "CU",
+      "id": 123,
+      "modifiedTime": "2015-07-28T11:40:09.520+02:00"
+    },
+    {
+      "action": "CU",
+      "id": 456,
+      "modifiedTime": "2015-07-28T11:42:29.510+02:00"
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.xml b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.xml
new file mode 100644
index 0000000..446e310
--- /dev/null
+++ b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSplitWriteAsStringTest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+            http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <split>
+        <jsonpath writeAsString="true">$.content</jsonpath>
+        <to uri="mock:line"/>
+        <to uri="log:line"/>
+      </split>
+    </route>
+  </camelContext>
+
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/5aa5ef9b/platforms/spring-boot/components-starter/camel-jsonpath-starter/src/main/java/org/apache/camel/jsonpath/springboot/JsonPathLanguageConfiguration.java
----------------------------------------------------------------------
diff --git a/platforms/spring-boot/components-starter/camel-jsonpath-starter/src/main/java/org/apache/camel/jsonpath/springboot/JsonPathLanguageConfiguration.java b/platforms/spring-boot/components-starter/camel-jsonpath-starter/src/main/java/org/apache/camel/jsonpath/springboot/JsonPathLanguageConfiguration.java
index 1528d28..54b098b 100644
--- a/platforms/spring-boot/components-starter/camel-jsonpath-starter/src/main/java/org/apache/camel/jsonpath/springboot/JsonPathLanguageConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-jsonpath-starter/src/main/java/org/apache/camel/jsonpath/springboot/JsonPathLanguageConfiguration.java
@@ -44,6 +44,11 @@ public class JsonPathLanguageConfiguration
      */
     private Boolean allowEasyPredicate = true;
     /**
+     * Whether to write the output of each row/element as a JSon String value
+     * instead of a Map/POJO value.
+     */
+    private Boolean writeAsString = false;
+    /**
      * Whether to trim the value to remove leading and trailing whitespaces and
      * line breaks
      */
@@ -73,6 +78,14 @@ public class JsonPathLanguageConfiguration
         this.allowEasyPredicate = allowEasyPredicate;
     }
 
+    public Boolean getWriteAsString() {
+        return writeAsString;
+    }
+
+    public void setWriteAsString(Boolean writeAsString) {
+        this.writeAsString = writeAsString;
+    }
+
     public Boolean getTrim() {
         return trim;
     }