github.com/kaptinlin/jsonschema@v0.4.6/content.go (about) 1 package jsonschema 2 3 // EvaluateContent checks if the given data conforms to the encoding, media type, and content schema specified in the schema. 4 // According to the JSON Schema Draft 2020-12: 5 // - The "contentEncoding" property defines how a string should be decoded from encoded binary data. 6 // - The "contentMediaType" describes the media type that the decoded data should conform to. 7 // - The "contentSchema" provides a schema to validate the structure of the decoded and unmarshalled data. 8 // 9 // This method ensures that the data instance conforms to the encoding, media type, and content schema constraints defined in the schema. 10 // If any stage fails, it returns a EvaluationError detailing the specific failure. 11 // 12 // References: 13 // - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentencoding 14 // - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentmediatype 15 // - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentschema 16 func evaluateContent(schema *Schema, instance interface{}, _ map[string]bool, _ map[int]bool, dynamicScope *DynamicScope) (*EvaluationResult, *EvaluationError) { 17 value, isString := instance.(string) 18 if !isString { 19 return nil, nil // If instance is not a string, content validation is not applicable. 20 } 21 22 var content []byte 23 var parsedValue interface{} 24 var err error 25 26 // Decode the content if encoding is specified 27 if schema.ContentEncoding != nil { 28 decoder, exists := schema.compiler.Decoders[*schema.ContentEncoding] 29 if !exists { 30 return nil, NewEvaluationError("contentEncoding", "unsupported_encoding", "Encoding '{encoding}' is not supported", map[string]interface{}{ 31 "encoding": *schema.ContentEncoding, 32 }) 33 } 34 content, err = decoder(value) 35 if err != nil { 36 return nil, NewEvaluationError("contentEncoding", "invalid_encoding", "Error decoding data with '{encoding}'", map[string]interface{}{ 37 "encoding": *schema.ContentEncoding, 38 "error": err.Error(), 39 }) 40 } 41 } else { 42 content = []byte(value) // Assume the content is the raw string if no encoding is specified 43 } 44 45 // Handle content media type validation 46 if schema.ContentMediaType != nil { 47 unmarshal, exists := schema.compiler.MediaTypes[*schema.ContentMediaType] 48 if !exists { 49 return nil, NewEvaluationError("contentMediaType", "unsupported_media_type", "Media type '{media_type}' is not supported", map[string]interface{}{ 50 "media_type": *schema.ContentMediaType, 51 }) 52 } 53 parsedValue, err = unmarshal(content) 54 if err != nil { 55 return nil, NewEvaluationError("contentMediaType", "invalid_media_type", "Error unmarshalling data with media type '{media_type}'", map[string]interface{}{ 56 "media_type": *schema.ContentMediaType, 57 "error": err.Error(), 58 }) 59 } 60 } else { 61 parsedValue = content // If no media type is specified, pass the raw content 62 } 63 64 // Evaluate against the content schema if specified and value was decoded 65 if schema.ContentSchema != nil { 66 result, _, _ := schema.ContentSchema.evaluate(parsedValue, dynamicScope) 67 if result != nil { 68 //nolint:errcheck 69 result.SetEvaluationPath("/contentSchema"). 70 SetSchemaLocation(schema.GetSchemaLocation("/contentSchema")). 71 SetInstanceLocation("") 72 73 if !result.IsValid() { 74 return result, NewEvaluationError("contentSchema", "content_schema_mismatch", "Content does not match the schema") 75 } else { 76 return result, nil 77 } 78 } 79 } 80 81 return nil, nil 82 }