Skip to content

Commit

Permalink
Handle non-json files when validating a directory (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
alenkacz authored Feb 13, 2018
1 parent a94d605 commit 6cfa905
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Provides json validation as a part of your gradle build pipeline.

This plugin implements a custom task type, [ValidateJsonTask](https://github.com/alenkacz/gradle-json-validator/blob/master/src/main/groovy/cz/alenkacz/gradle/jsonvalidator/ValidateJsonTask.groovy). This task expects two properties - *targetJsonFile* and *jsonSchemaFile* (instead of *targetJsonFile* you can use *targetJsonDirectory* and then all files in that directory will be validated). If you need to validate more jsons as a part of one build, you will have to create as many custom tasks as the number of json schema files (see *validateCustomJson* in the example below).
This plugin implements a custom task type, [ValidateJsonTask](https://github.com/alenkacz/gradle-json-validator/blob/master/src/main/groovy/cz/alenkacz/gradle/jsonvalidator/ValidateJsonTask.groovy). This task expects two properties - *targetJsonFile* and *jsonSchemaFile* (instead of *targetJsonFile* you can use *targetJsonDirectory* and then all files in that directory will be validated). If that directory contains both json and non-json files, the task will fail for non-json files. If you want to validate only files with .json extension use the `onlyWithJsonExtension` property. If you need to validate more jsons as a part of one build, you will have to create as many custom tasks as the number of json schema files (see *validateCustomJson* in the example below).

Usage
====================
Expand All @@ -26,6 +26,7 @@ Usage
targetJsonFile = file("target.json") // only one of targetJsonFile or targetJsonDirectory can be specified
targetJsonDirectory = file("directoryWithJsons") // only one of targetJsonFile or targetJsonDirectory can be specified
jsonSchema = file("schema.json")
onlyWithJsonExtension = true // default is false, this makes sense only when using targetJsonDirectory, it ignores all files apart from those who do not have .json file extension
}

JSON schema syntax check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.InputFile
import org.json.JSONException
import org.json.JSONObject
import org.json.JSONTokener

Expand All @@ -23,10 +24,18 @@ class ValidateJsonTask extends DefaultTask {
@InputDirectory
@Optional
File targetJsonDirectory
@Optional
Boolean onlyWithJsonExtension

@TaskAction
def validateJson() {
// check files exist
if (onlyWithJsonExtension != null && targetJsonDirectory == null) {
throw new IllegalArgumentException("Cannot use onlyWithJsonExtension property without using targetJsonDirectory.")
}
if (onlyWithJsonExtension == null) {
onlyWithJsonExtension = false
}
new FileInputStream(jsonSchema).withStream {
JSONObject rawSchema = new JSONObject(new JSONTokener(it))
Schema schema = SchemaLoader.load(rawSchema)
Expand All @@ -44,6 +53,11 @@ class ValidateJsonTask extends DefaultTask {
schema.validate(new JSONObject(new FileInputStream(it).getText()))
} catch (ValidationException e) {
violations << new ValidationError(jsonFilePath: it.absolutePath, violations: getViolations(e))
} catch (JSONException e) {
if (!onlyWithJsonExtension || hasJsonExtension(it)) {
// invalid json file is considered a violation only when onlyWithJsonExtension is not used or if the file does not have json extension
violations << new ValidationError(jsonFilePath: it.absolutePath, violations: ["File is not valid json: ${e.message}"])
}
}
}
if (!violations.empty) {
Expand All @@ -52,6 +66,10 @@ class ValidateJsonTask extends DefaultTask {
}
}

def hasJsonExtension(File file) {
file.name.contains(".") && file.name.take(file.name.lastIndexOf('.')) == "json"
}

List<String> getViolations(ValidationException e) {
if (e.causingExceptions.empty) {
[e.message]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,45 @@ class ValidateJsonTaskTest extends Specification {
actual.task(":validateCustomJson").outcome == TaskOutcome.FAILED
}

def "fail on non-json file"() {
given:
final FileTreeBuilder treeBuilder = new FileTreeBuilder(targetProjectDir.newFolder("non-json-folder"))
treeBuilder.file("test.json", getInvalidJson())
treeBuilder.file("nonjson.txt", "randomtext")
gradleBuildFile.text = getFolderGradleFile("non-json-folder")
jsonSchemaFile << getJsonSchema()

when:
def actual = GradleRunner.create()
.withProjectDir(targetProjectDir.root)
.withArguments(':validateCustomJson', '--stacktrace')
.buildAndFail()

then:
actual.output.contains("File is not valid json")
actual.output.contains("nonjson.txt")
actual.task(":validateCustomJson").outcome == TaskOutcome.FAILED
}

def "not fail on non-json file when using onlyWithJsonExtension"() {
given:
final FileTreeBuilder treeBuilder = new FileTreeBuilder(targetProjectDir.newFolder("non-json-folder"))
treeBuilder.file("test.json", getCorrectJson())
treeBuilder.file("nonjson.txt", "randomtext")
gradleBuildFile.text = getFolderGradleFile("non-json-folder", true)
jsonSchemaFile << getJsonSchema()

when:
def actual = GradleRunner.create()
.withProjectDir(targetProjectDir.root)
.withArguments(':validateCustomJson', '--stacktrace')
.build()

then:
print(actual.output)
actual.task(":validateCustomJson").outcome == TaskOutcome.SUCCESS
}

def getCorrectJson() {
'''
{
Expand Down Expand Up @@ -139,7 +178,7 @@ class ValidateJsonTaskTest extends Specification {
"""
}

def getFolderGradleFile() {
def getFolderGradleFile(folderName = "json", onlyWithJsonExtension = false) {
"""
buildscript {
dependencies {
Expand All @@ -151,8 +190,9 @@ class ValidateJsonTaskTest extends Specification {
import cz.alenkacz.gradle.jsonvalidator.ValidateJsonTask
task validateCustomJson(type: ValidateJsonTask) {
targetJsonDirectory = file("json")
targetJsonDirectory = file("$folderName")
jsonSchema = project.file("schema.json")
onlyWithJsonExtension = ${onlyWithJsonExtension ? "true" : "false"}
}
"""
}
Expand Down

0 comments on commit 6cfa905

Please sign in to comment.