diff --git a/Examples/JSONSchemaValidatorHelper.swift b/Examples/JSONSchemaValidatorHelper.swift new file mode 100644 index 0000000..e647f2c --- /dev/null +++ b/Examples/JSONSchemaValidatorHelper.swift @@ -0,0 +1,50 @@ +// +// JSONSchemaValidatorHelper.swift +// +// Created by Geert Michiels on 24/01/2021. +// + +import Foundation +import JSONSchema +import Combine + +struct JSONSchemaValidatorHelper { + + private var fetchSchemaCancellable : AnyCancellable? + + ///loads the json schema from the specified url (using combine framework aka publishers) + mutating func loadJsonSchema(url: URL, completion: @escaping ([String: Any]?) -> Void) { + fetchSchemaCancellable = URLSession.shared.dataTaskPublisher(for: url) + //after receiving the data from the load, convert it to jsonObject that is representing our schema + .map { data, urlResponse in + try? JSONSerialization.jsonObject(with: data, options: []) + } + //don't care about the url loading errors, just return nil schema if this happens + .replaceError(with: nil) + //go and call ourpassed in completion handler when finished + .sink { value in + completion(value as? [String:Any]) + } + } + + ///converts the specified encodable object to json and validates it agains the specified schema url + mutating func validate(encodableObject: Object, againstSchemaUrl schemaUrl: URL, completion: @escaping (ValidationResult?) -> Void ) where Object: Encodable { + //first load our schema + loadJsonSchema(url: schemaUrl) { schema in + //check schema loaded successfully + guard let schema = schema else { + completion(ValidationResult.invalid(["Could not schema"])) + return + } + //convert our object to json + guard let jsonData = (try? JSONEncoder().encode(encodableObject)), + let jsonEquivalentFoundationObjects = (try? JSONSerialization.jsonObject(with: jsonData, options: [])) else { + completion(ValidationResult.invalid(["Could not convert 'encodableObject' to json equivalent foundation objects"])) + return + } + //perform validation and let our completion handler know the result + completion(JSONSchema.validate(jsonEquivalentFoundationObjects, schema: schema)) + } + } + +} diff --git a/README.md b/README.md index 1ce7801..aaab7ff 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ pod 'JSONSchema' ``` ## Usage +### Basic ```swift import JSONSchema @@ -27,8 +28,63 @@ JSONSchema.validate(["name": "Eggs", "price": 34.99], schema: [ "required": ["name"], ]) ``` +### JSONSchemaValidatorHelper.swift example +Inside the `Example` folder you can find `JSONSchemaValidatorHelper.swift`. +It shows how to load a json schema from a url and then validate it agains an object that confirms to the [Codable](https://developer.apple.com/documentation/swift/codable) protocol. -### Error handling +```swift +struct JSONSchemaValidatorHelper { + + private var fetchSchemaCancellable : AnyCancellable? + + ///loads the json schema from the specified url (using combine framework aka publishers) + mutating func loadJsonSchema(url: URL, completion: @escaping ([String: Any]?) -> Void) { + fetchSchemaCancellable = URLSession.shared.dataTaskPublisher(for: url) + //after receiving the data from the load, convert it to jsonObject that is representing our schema + .map { data, urlResponse in + try? JSONSerialization.jsonObject(with: data, options: []) + } + //don't care about the url loading errors, just return nil schema if this happens + .replaceError(with: nil) + //go and call ourpassed in completion handler when finished + .sink { value in + completion(value as? [String:Any]) + } + } + + ///converts the specified encodable object to json and validates it agains the specified schema url + mutating func validate(encodableObject: Object, againstSchemaUrl schemaUrl: URL, completion: @escaping (ValidationResult?) -> Void ) where Object: Encodable { + //first load our schema + loadJsonSchema(url: schemaUrl) { schema in + //check schema loaded successfully + guard let schema = schema else { + completion(ValidationResult.invalid(["Could not schema"])) + return + } + //convert our object to json + guard let jsonData = (try? JSONEncoder().encode(encodableObject)), + let jsonEquivalentFoundationObjects = (try? JSONSerialization.jsonObject(with: jsonData, options: [])) else { + completion(ValidationResult.invalid(["Could not convert 'encodableObject' to json equivalent foundation objects"])) + return + } + //perform validation and let our completion handler know the result + completion(JSONSchema.validate(jsonEquivalentFoundationObjects, schema: schema)) + } + } + +} +``` + +This is how to use it: + +```swift + let schemaUrl = URL(string: "https://path.to.your.schema.json")! + jsonSchema.validate(encodableObject: snookerTable, againstSchemaUrl: schemaUrl) { result in + print(result) + } +``` + +## Error handling Validate returns an enumeration `ValidationResult` which contains all validation errors.