mirror of https://github.com/apache/nifi.git
NIFI-5261: Added JSON_VALIDATOR to StandardValidators
This closes #2758 Signed-off-by: Mike Thomsen <mikerthomsen@gmail.com>
This commit is contained in:
parent
cb216b79ec
commit
504152eaa1
|
@ -40,5 +40,10 @@
|
|||
<artifactId>nifi-api</artifactId>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -30,6 +30,9 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import org.apache.nifi.components.PropertyValue;
|
||||
import org.apache.nifi.components.ValidationContext;
|
||||
import org.apache.nifi.components.ValidationResult;
|
||||
|
@ -480,6 +483,25 @@ public class StandardValidators {
|
|||
|
||||
public static final Validator FILE_EXISTS_VALIDATOR = new FileExistsValidator(true);
|
||||
|
||||
/**
|
||||
* {@link Validator} that ensures the value is a valid JSON
|
||||
*/
|
||||
public static final Validator JSON_VALIDATOR = (subject, input, context) -> {
|
||||
if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) {
|
||||
return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build();
|
||||
}
|
||||
|
||||
try {
|
||||
new Gson().fromJson(input, JsonElement.class);
|
||||
} catch (JsonSyntaxException e) {
|
||||
return new ValidationResult.Builder().subject(subject).input(input).valid(false)
|
||||
.explanation(subject + " is not a valid JSON representation due to " + e.getLocalizedMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
return new ValidationResult.Builder().subject(subject).input(input).valid(true).build();
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
// FACTORY METHODS FOR VALIDATORS
|
||||
|
|
|
@ -288,4 +288,42 @@ public class TestStandardValidators {
|
|||
vr = val.validate("foo", "2016-01-01T01:01:01.000Z", vc);
|
||||
assertTrue(vr.isValid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJSONObjectValidator() {
|
||||
final Validator validator = StandardValidators.JSON_VALIDATOR;
|
||||
final ValidationContext context = mock(ValidationContext.class);
|
||||
final String DUMMY_JSON_PROPERTY = "JSONProperty";
|
||||
ValidationResult validationResult;
|
||||
|
||||
// Flat JSON
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY,"{\"Name\" : \"Crockford, Douglas\"}", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// Nested JSON
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "{ \"Name\" : \"Crockford, Douglas\", \"ContactInfo\": { \"Mobile\" : 0987654321, \"Email\" : \"mrx@xyz.zyx\" } }", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// JSON object with JSON array
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "{ \"name\":\"Smith, John\", \"age\":30, \"cars\":[ \"Ford\", \"BMW\", \"Fiat\" ] } ", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// JSON array
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "[\"one\", \"two\", \"three\"]", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// JSON Primitives
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "bncjbhjfjhj", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// Empty JSON
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "{}", context);
|
||||
assertTrue(validationResult.isValid());
|
||||
|
||||
// Invalid JSON
|
||||
validationResult = validator.validate(DUMMY_JSON_PROPERTY, "\"Name\" : \"Smith, John\"", context);
|
||||
assertFalse(validationResult.isValid());
|
||||
assertTrue(validationResult.getExplanation().contains("not a valid JSON representation"));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public interface ElasticSearchRestProcessor {
|
|||
"If this parameter is not set, the query will be read from the flowfile content.")
|
||||
.required(false)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.build();
|
||||
PropertyDescriptor QUERY_ATTRIBUTE = new PropertyDescriptor.Builder()
|
||||
.name("el-query-attribute")
|
||||
|
|
|
@ -83,7 +83,7 @@ public final class CredentialPropertyDescriptors {
|
|||
.displayName("Service Account JSON")
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
|
||||
.required(false)
|
||||
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.description("The raw JSON containing a Service Account keyfile.")
|
||||
.sensitive(true)
|
||||
.build();
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
|||
import org.apache.nifi.annotation.documentation.Tags;
|
||||
import org.apache.nifi.components.AllowableValue;
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.components.ValidationResult;
|
||||
import org.apache.nifi.components.Validator;
|
||||
import org.apache.nifi.expression.ExpressionLanguageScope;
|
||||
import org.apache.nifi.flowfile.FlowFile;
|
||||
|
@ -60,23 +59,6 @@ import java.util.Set;
|
|||
@InputRequirement(Requirement.INPUT_ALLOWED)
|
||||
@CapabilityDescription("Creates FlowFiles from documents in MongoDB")
|
||||
public class GetMongo extends AbstractMongoProcessor {
|
||||
public static final Validator DOCUMENT_VALIDATOR = (subject, value, context) -> {
|
||||
final ValidationResult.Builder builder = new ValidationResult.Builder();
|
||||
builder.subject(subject).input(value);
|
||||
|
||||
if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(value)) {
|
||||
return builder.valid(true).explanation("Contains Expression Language").build();
|
||||
}
|
||||
|
||||
String reason = null;
|
||||
try {
|
||||
Document.parse(value);
|
||||
} catch (final RuntimeException e) {
|
||||
reason = e.getLocalizedMessage();
|
||||
}
|
||||
|
||||
return builder.explanation(reason).valid(reason == null).build();
|
||||
};
|
||||
|
||||
static final Relationship REL_SUCCESS = new Relationship.Builder().name("success").description("All files are routed to success").build();
|
||||
static final Relationship REL_FAILURE = new Relationship.Builder()
|
||||
|
@ -97,7 +79,7 @@ public class GetMongo extends AbstractMongoProcessor {
|
|||
"that will result in a full collection fetch using a \"{}\" query.")
|
||||
.required(false)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.addValidator(DOCUMENT_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.build();
|
||||
|
||||
static final PropertyDescriptor PROJECTION = new PropertyDescriptor.Builder()
|
||||
|
@ -105,14 +87,14 @@ public class GetMongo extends AbstractMongoProcessor {
|
|||
.description("The fields to be returned from the documents in the result set; must be a valid BSON document")
|
||||
.required(false)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.addValidator(DOCUMENT_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.build();
|
||||
static final PropertyDescriptor SORT = new PropertyDescriptor.Builder()
|
||||
.name("Sort")
|
||||
.description("The fields by which to sort; must be a valid BSON document")
|
||||
.required(false)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.addValidator(DOCUMENT_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.build();
|
||||
static final PropertyDescriptor LIMIT = new PropertyDescriptor.Builder()
|
||||
.name("Limit")
|
||||
|
|
|
@ -100,7 +100,7 @@ public class PutMongo extends AbstractMongoProcessor {
|
|||
.displayName("Update Query")
|
||||
.description("Specify a full MongoDB query to be used for the lookup query to do an update/upsert.")
|
||||
.required(false)
|
||||
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.build();
|
||||
|
||||
|
|
|
@ -28,14 +28,13 @@ import org.apache.nifi.annotation.behavior.InputRequirement;
|
|||
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||
import org.apache.nifi.annotation.documentation.Tags;
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.components.ValidationResult;
|
||||
import org.apache.nifi.components.Validator;
|
||||
import org.apache.nifi.expression.ExpressionLanguageScope;
|
||||
import org.apache.nifi.flowfile.FlowFile;
|
||||
import org.apache.nifi.processor.ProcessContext;
|
||||
import org.apache.nifi.processor.ProcessSession;
|
||||
import org.apache.nifi.processor.Relationship;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
@ -83,31 +82,13 @@ public class RunMongoAggregation extends AbstractMongoProcessor {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static final Validator AGG_VALIDATOR = (subject, value, context) -> {
|
||||
final ValidationResult.Builder builder = new ValidationResult.Builder();
|
||||
builder.subject(subject).input(value);
|
||||
|
||||
if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(value)) {
|
||||
return builder.valid(true).explanation("Contains Expression Language").build();
|
||||
}
|
||||
|
||||
String reason = null;
|
||||
try {
|
||||
buildAggregationQuery(value);
|
||||
} catch (final RuntimeException | IOException e) {
|
||||
reason = e.getLocalizedMessage();
|
||||
}
|
||||
|
||||
return builder.explanation(reason).valid(reason == null).build();
|
||||
};
|
||||
|
||||
static final PropertyDescriptor QUERY = new PropertyDescriptor.Builder()
|
||||
.name("mongo-agg-query")
|
||||
.displayName("Query")
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
|
||||
.description("The aggregation query to be executed.")
|
||||
.required(true)
|
||||
.addValidator(AGG_VALIDATOR)
|
||||
.addValidator(StandardValidators.JSON_VALIDATOR)
|
||||
.build();
|
||||
|
||||
static {
|
||||
|
|
Loading…
Reference in New Issue