/// <summary> /// Validates the value of json according to an implicit schmea defined by expectedJson /// </summary> /// <returns></returns> public bool ValidateJsonExample(CodeBlockAnnotation expectedResponseAnnotation, string actualResponseBodyJson, IssueLogger issues, ValidationOptions options = null) { List <ValidationError> newErrors = new List <ValidationError>(); var resourceType = expectedResponseAnnotation.ResourceType; if (resourceType == "stream") { // No validation since we're streaming data return(true); } else { JsonSchema schema; if (string.IsNullOrEmpty(resourceType)) { schema = JsonSchema.EmptyResponseSchema; } else if (!this.registeredSchema.TryGetValue(resourceType, out schema)) { newErrors.Add(new ValidationWarning(ValidationErrorCode.ResponseResourceTypeMissing, null, "Missing required resource: {0}. Validation limited to basics only.", resourceType)); // Create a new schema based on what's available in the json schema = new JsonSchema(actualResponseBodyJson, new CodeBlockAnnotation { ResourceType = expectedResponseAnnotation.ResourceType }); } this.ValidateJsonCompilesWithSchema(schema, new JsonExample(actualResponseBodyJson, expectedResponseAnnotation), issues, options: options); return(issues.Issues.Count() == 0); } }
public ValidationOptions(CodeBlockAnnotation annotation) { if (null == annotation) return; this.CollectionPropertyName = annotation.CollectionPropertyName; this.AllowTruncatedResponses = annotation.TruncatedResult; }
private void ValidateCollectionObject(JContainer obj, CodeBlockAnnotation annotation, Dictionary <string, JsonSchema> otherSchemas, string collectionPropertyName, List <ValidationError> detectedErrors, ValidationOptions options) { // TODO: also validate additional properties on the collection, like nextDataLink var collection = obj[collectionPropertyName]; if (null == collection) { detectedErrors.Add(new ValidationError(ValidationErrorCode.MissingCollectionProperty, null, "Failed to locate collection property '{0}' in response.", collectionPropertyName)); } else { var collectionMembers = obj[collectionPropertyName]; if (!collectionMembers.Any()) { if (!annotation.IsEmpty) { detectedErrors.Add( new ValidationWarning( ValidationErrorCode.CollectionArrayEmpty, null, "Property contained an empty array that was not validated: {0}", collectionPropertyName)); } } else if (annotation.IsEmpty) { detectedErrors.Add( new ValidationWarning( ValidationErrorCode.CollectionArrayNotEmpty, null, "Property contained a non-empty array that was expected to be empty: {0}", collectionPropertyName)); } foreach (var jToken in collectionMembers) { var container = jToken as JContainer; if (null != container) { List <ValidationError> containerErrors = new List <ValidationError>(); var deeperOptions = new ValidationOptions(options) { AllowTruncatedResponses = annotation.TruncatedResult }; this.ValidateContainerObject( container, deeperOptions, otherSchemas, containerErrors); detectedErrors.AddUniqueErrors(containerErrors); } } } }
public ValidationOptions(CodeBlockAnnotation annotation) { if (null == annotation) { return; } this.CollectionPropertyName = annotation.CollectionPropertyName; this.AllowTruncatedResponses = annotation.TruncatedResult; }
private static ResourceDefinition ResourceDefinitionFromType(Schema schema, IEnumerable <Schema> otherSchema, ComplexType ct, IssueLogger issues) { var annotation = new CodeBlockAnnotation() { ResourceType = string.Concat(schema.Namespace, ".", ct.Name), BlockType = CodeBlockType.Resource }; var json = BuildJsonExample(ct, otherSchema); ResourceDefinition rd = new JsonResourceDefinition(annotation, json, null, issues); return(rd); }
public JsonSchema SchemaForNullTest(bool expectNulls) { var schemaObject = new { prop1 = "string", prop2 = 12345 }; string json = JsonConvert.SerializeObject(schemaObject); var annotation = new CodeBlockAnnotation { NullableProperties = expectNulls ? new string[] { "prop1", "prop2" } : new string[0] }; return(new JsonSchema(json, annotation)); }
private static ResourceDefinition ResourceDefinitionFromType(Schema schema, IEnumerable <Schema> otherSchema, ComplexType ct, IssueLogger issues, MetadataValidationConfigs metadataValidationConfigs) { var resourceType = BuildResourceTypeIdentifer( schema.Namespace, metadataValidationConfigs?.ModelConfigs?.AliasNamespace, ct.Name, metadataValidationConfigs?.ModelConfigs?.ValidateNamespace); var annotation = new CodeBlockAnnotation() { ResourceType = resourceType, BlockType = CodeBlockType.Resource }; var json = BuildJsonExample(ct, otherSchema, metadataValidationConfigs); ResourceDefinition rd = new JsonResourceDefinition(annotation, json, null, issues); return(rd); }
public JsonSchema(string json, CodeBlockAnnotation annotation) { this.Metadata = annotation; this.ExpectedProperties = this.BuildSchemaFromJson(json); }
private void ValidateCollectionObject(JContainer obj, CodeBlockAnnotation annotation, Dictionary <string, JsonSchema> otherSchemas, string collectionPropertyName, IssueLogger issues, ValidationOptions options) { // TODO: also validate additional properties on the collection, like nextDataLink JToken collection = null; if (obj is JArray) { collection = obj; } else { try { collection = obj[collectionPropertyName]; } catch (Exception ex) { issues.Error(ValidationErrorCode.JsonErrorObjectExpected, $"Unable to find collection parameter or array to validate: {ex.Message}"); return; } } if (null == collection) { issues.Error(ValidationErrorCode.MissingCollectionProperty, $"Failed to locate collection property '{collectionPropertyName}' in response."); } else { if (!collection.Any()) { if (!annotation.IsEmpty) { issues.Warning( ValidationErrorCode.CollectionArrayEmpty, $"Property contained an empty array that was not validated: {collectionPropertyName}"); } } else if (annotation.IsEmpty) { issues.Warning( ValidationErrorCode.CollectionArrayNotEmpty, $"Property contained a non-empty array that was expected to be empty: {collectionPropertyName}"); } foreach (var jToken in collection) { var container = jToken as JContainer; if (null != container) { var deeperOptions = new ValidationOptions(options) { AllowTruncatedResponses = annotation.TruncatedResult }; this.ValidateContainerObject( container, deeperOptions, otherSchemas, issues.For("container", onlyKeepUniqueErrors: true)); } } } }
/// <summary> /// Validates the value of json according to an implicit schmea defined by expectedJson /// </summary> /// <param name="expectedResponseAnnotation"></param> /// <param name="actualResponseBodyJson"></param> /// <param name="errors"></param> /// <returns></returns> public bool ValidateJsonExample(CodeBlockAnnotation expectedResponseAnnotation, string actualResponseBodyJson, out ValidationError[] errors, ValidationOptions options = null) { List<ValidationError> newErrors = new List<ValidationError>(); var resourceType = expectedResponseAnnotation.ResourceType; if (resourceType == "stream") { // No validation since we're streaming data errors = null; return true; } else { JsonSchema schema; if (string.IsNullOrEmpty(resourceType)) { schema = JsonSchema.EmptyResponseSchema; } else if (!this.registeredSchema.TryGetValue(resourceType, out schema)) { newErrors.Add(new ValidationWarning(ValidationErrorCode.ResponseResourceTypeMissing, null, "Missing required resource: {0}. Validation limited to basics only.", resourceType)); // Create a new schema based on what's avaiable in the json schema = new JsonSchema(actualResponseBodyJson, new CodeBlockAnnotation { ResourceType = expectedResponseAnnotation.ResourceType }); } ValidationError[] validationJsonOutput; this.ValidateJsonCompilesWithSchema(schema, new JsonExample(actualResponseBodyJson, expectedResponseAnnotation), out validationJsonOutput, options: options); newErrors.AddRange(validationJsonOutput); errors = newErrors.ToArray(); return errors.Length == 0; } }
private void ValidateCollectionObject(JContainer obj, CodeBlockAnnotation annotation, Dictionary<string, JsonSchema> otherSchemas, string collectionPropertyName, List<ValidationError> detectedErrors) { // TODO: also validate additional properties on the collection, like nextDataLink var collection = obj[collectionPropertyName]; if (null == collection) { detectedErrors.Add(new ValidationError(ValidationErrorCode.MissingCollectionProperty, null, "Failed to locate collection property '{0}' in response.", collectionPropertyName)); } else { var collectionMembers = obj[collectionPropertyName]; if (!collectionMembers.Any()) { if (!annotation.IsEmpty) { detectedErrors.Add( new ValidationWarning( ValidationErrorCode.CollectionArrayEmpty, null, "Property contained an empty array that was not validated: {0}", collectionPropertyName)); } } else if (annotation.IsEmpty) { detectedErrors.Add( new ValidationWarning( ValidationErrorCode.CollectionArrayNotEmpty, null, "Property contained a non-empty array that was expected to be empty: {0}", collectionPropertyName)); } foreach (var jToken in collectionMembers) { var container = jToken as JContainer; if (null != container) { this.ValidateContainerObject( container, new ValidationOptions { AllowTruncatedResponses = annotation.TruncatedResult }, otherSchemas, detectedErrors); } } } }
public JsonExample(string json, CodeBlockAnnotation annotation = null) { this.JsonData = json; this.Annotation = annotation ?? new CodeBlockAnnotation(); }
private static ResourceDefinition ResourceDefinitionFromType(Schema schema, IEnumerable<Schema> otherSchema, ComplexType ct) { var annotation = new CodeBlockAnnotation() { ResourceType = string.Concat(schema.Namespace, ".", ct.Name), BlockType = CodeBlockType.Resource }; var json = BuildJsonExample(ct, otherSchema); ResourceDefinition rd = new JsonResourceDefinition(annotation, json, null); return rd; }
public JsonSchema SchemaForNullTest(bool expectNulls) { var schemaObject = new { prop1 = "string", prop2 = 12345 }; string json = JsonConvert.SerializeObject(schemaObject); var annotation = new CodeBlockAnnotation { NullableProperties = expectNulls ? new string[] { "prop1", "prop2" } : new string[0] }; return new JsonSchema(json, annotation); }