diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/SplitJson.java b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/SplitJson.java index e589b487ca..3ca0ace098 100644 --- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/SplitJson.java +++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/SplitJson.java @@ -18,6 +18,7 @@ package org.apache.nifi.processors.standard; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.PathNotFoundException; import org.apache.nifi.annotation.behavior.EventDriven; import org.apache.nifi.annotation.behavior.SideEffectFree; import org.apache.nifi.annotation.behavior.SupportsBatching; @@ -105,10 +106,17 @@ public class SplitJson extends AbstractProcessor { final List segments = new ArrayList<>(); - Object jsonPathResult = documentContext.read(jsonPath); + Object jsonPathResult; + try { + jsonPathResult = documentContext.read(jsonPath); + } catch (PathNotFoundException e) { + logger.warn("JsonPath {} could not be found for FlowFile {}", new Object[]{jsonPath.getPath(), original}); + processSession.transfer(original, REL_FAILURE); + return; + } if (!(jsonPathResult instanceof List)) { - logger.error("The evaluated value {} of {} was not an array compatible type and cannot be split.", + logger.error("The evaluated value {} of {} was not a JSON Array compatible type and cannot be split.", new Object[]{jsonPathResult, jsonPath.getPath()}); processSession.transfer(original, REL_FAILURE); return; diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/JsonUtils.java b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/JsonUtils.java index 0bf33dd332..5fe2a5664d 100644 --- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/JsonUtils.java +++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/util/JsonUtils.java @@ -89,14 +89,23 @@ public class JsonUtils { return contextHolder.get(); } + /* + * JSONValue#isValidJson is permissive to the degree of the Smart JSON definition. + * Accordingly, a strict JSON approach is preferred in determining whether or not a document is valid. + */ + /** + * JSONValue#isValidJson is permissive to the degree of the Smart JSON definition, accordingly a strict JSON approach + * is preferred in determining whether or not a document is valid. + * Performs a validation of the provided stream according to RFC 4627 as implemented by {@link net.minidev.json.parser.JSONParser#MODE_RFC4627} + * + * @param inputStream of content to be validated as JSON + * @return true, if the content is valid within the bounds of the strictness specified; false otherwise + * @throws IOException + */ public static boolean isValidJson(InputStream inputStream) throws IOException { boolean isValid = false; - /* - * JSONValue#isValidJson is permissive to the degree of the Smart JSON definition. - * Accordingly, a strict JSON approach is preferred in determining whether or not a document is valid. - */ try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream)) { isValid = JSONValue.isValidJsonStrict(inputStreamReader); } @@ -104,8 +113,15 @@ public class JsonUtils { return isValid; } + /** + * Determines the context by which JsonSmartJsonProvider would treat the value. {@link java.util.Map} and + * {@link java.util.List} objects can be rendered as JSON elements, everything else is treated as a scalar. + * + * @param obj item to be inspected if it is a scalar or a JSON element + * @return false, if the object is a supported type; true otherwise + */ public static boolean isJsonScalar(Object obj) { - // For the default provider, a Map or List is able to be handled as a JSON entity + // For the default provider, JsonSmartJsonProvider, a Map or List is able to be handled as a JSON entity return !(obj instanceof Map || obj instanceof List); } diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestSplitJson.java b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestSplitJson.java index dd6fc6d703..f47467f28d 100644 --- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestSplitJson.java +++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestSplitJson.java @@ -112,4 +112,15 @@ public class TestSplitJson { testRunner.getFlowFilesForRelationship(SplitJson.REL_SPLIT).get(0).assertContentEquals("{\"first\":\"Shaffer\",\"last\":\"Pearson\"}"); } + @Test + public void testSplit_pathNotFound() throws Exception { + final TestRunner testRunner = TestRunners.newTestRunner(new SplitJson()); + testRunner.setProperty(SplitJson.ARRAY_JSON_PATH_EXPRESSION, "$.nonexistent"); + + testRunner.enqueue(JSON_SNIPPET); + testRunner.run(); + + testRunner.assertTransferCount(SplitJson.REL_FAILURE, 1); + testRunner.getFlowFilesForRelationship(SplitJson.REL_FAILURE).get(0).assertContentEquals(JSON_SNIPPET); + } }