ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

YAML Structure Validator with Schema

YAML

Goal -- WPM

Ready
Exercise Algorithm Area
1package com.example.yaml;
2
3import java.util.List;
4import java.util.Map;
5import java.util.Set;
6import java.util.HashSet;
7import java.util.ArrayList;
8
9public class YamlSchemaValidator {
10
11// Main validation function.
12public List<ValidationError> validate(Object yamlData, YamlSchema schema) {
13List<ValidationError> errors = new ArrayList<>();
14validateRecursive(yamlData, schema.getRootSchema(), "", errors);
15return errors;
16}
17
18// Recursive helper for validation.
19private void validateRecursive(Object data, SchemaNode schemaNode, String path, List<ValidationError> errors) {
20if (schemaNode == null) {
21// Schema node is missing, consider this an error in schema definition
22errors.add(new ValidationError(path, "Schema definition error: missing node."));
23return;
24}
25
26// Type checking
27if (!isTypeMatch(data, schemaNode.getType())) {
28errors.add(new ValidationError(path, "Expected type '" + schemaNode.getType() + "', but found '" + (data == null ? "null" : data.getClass().getSimpleName()) + "'."));
29return; // Stop further validation for this branch if type mismatch
30}
31
32if (data == null) {
33// Null data is valid if the schema allows it (e.g., optional field)
34// If schemaNode.isRequired() is true and data is null, it's an error handled by caller.
35return;
36}
37
38// Specific validation based on schema node type
39switch (schemaNode.getType()) {
40case "object":
41if (!(data instanceof Map)) { /* Type check already done */ return; }
42Map<?, ?> dataMap = (Map<?, ?>) data;
43// Validate required properties
44for (String requiredProp : schemaNode.getRequiredProperties()) {
45if (!dataMap.containsKey(requiredProp)) {
46errors.add(new ValidationError(path + "." + requiredProp, "Required property '" + requiredProp + "' is missing."));
47}
48}
49// Validate properties defined in schema
50for (Map.Entry<?, ?> entry : dataMap.entrySet()) {
51String key = entry.getKey().toString();
52SchemaNode propertySchema = schemaNode.getPropertySchema(key);
53if (propertySchema != null) {
54validateRecursive(entry.getValue(), propertySchema, path + "." + key, errors);
55} else if (!schemaNode.isAllowAdditionalProperties()) {
56errors.add(new ValidationError(path + "." + key, "Unexpected property '" + key + "'."));
57}
58}
59break;
60case "array":
61if (!(data instanceof List)) { /* Type check already done */ return; }
62List<?> dataList = (List<?>) data;
63SchemaNode itemsSchema = schemaNode.getItemsSchema();
64if (itemsSchema != null) {
65for (int i = 0; i < dataList.size(); i++) {
66validateRecursive(dataList.get(i), itemsSchema, path + "[" + i + "]", errors);
67}
68}
69// Additional array constraints like minItems, maxItems could be added here.
70break;
71case "string":
72// String specific validations like minLength, maxLength, pattern could be added.
73break;
74case "integer":
75case "number":
76// Number specific validations like minimum, maximum could be added.
77break;
78case "boolean":
79// No specific validation needed beyond type check.
80break;
81default:
82// Unknown schema type
83errors.add(new ValidationError(path, "Unknown schema type: '" + schemaNode.getType() + "'."));
84break;
85}
86}
87
88// Helper to check if data type matches schema type.
89private boolean isTypeMatch(Object data, String schemaType) {
90if (data == null) return true; // Null is generally acceptable unless explicitly disallowed by schema (e.g. required)
91switch (schemaType) {
92case "object": return data instanceof Map;
93case "array": return data instanceof List;
94case "string": return data instanceof String;
95case "integer": return data instanceof Integer;
96case "number": return data instanceof Integer || data instanceof Double || data instanceof Float;
97case "boolean": return data instanceof Boolean;
98default: return false;
99}
100}
101
102// Placeholder for SchemaNode and ValidationError classes
103// These would define the structure of the schema and validation errors.
104
105public static class SchemaNode {
106private String type;
107private Set<String> requiredProperties = new HashSet<>();
108private Map<String, SchemaNode> properties = new java.util.HashMap<>();
109private SchemaNode itemsSchema;
110private boolean allowAdditionalProperties = false;
111
112public SchemaNode(String type) { this.type = type; }
113public String getType() { return type; }
114public void addRequiredProperty(String prop) { requiredProperties.add(prop); }
115public Set<String> getRequiredProperties() { return requiredProperties; }
116public void addProperty(String name, SchemaNode schema) { properties.put(name, schema); }
117public SchemaNode getPropertySchema(String name) { return properties.get(name); }
118public void setItemsSchema(SchemaNode itemsSchema) { this.itemsSchema = itemsSchema; }
119public SchemaNode getItemsSchema() { return itemsSchema; }
120public void setAllowAdditionalProperties(boolean allow) { allowAdditionalProperties = allow; }
121public boolean isAllowAdditionalProperties() { return allowAdditionalProperties; }
122}
123
124public static class YamlSchema {
125private SchemaNode rootSchema;
126public YamlSchema(SchemaNode root) { this.rootSchema = root; }
127public SchemaNode getRootSchema() { return rootSchema; }
128}
129
130public static class ValidationError {
131private String path;
132private String message;
133public ValidationError(String path, String message) { this.path = path; this.message = message; }
134public String getPath() { return path; }
135public String getMessage() { return message; }
136@Override public String toString() { return "ValidationError{path='" + path + "', message='" + message + "'}"; }
137}
138
139public static void main(String[] args) {
140// Example usage: create a schema, load YAML data, and validate.
141}
142}
Algorithm description viewbox

YAML Structure Validator with Schema

Algorithm description:

This algorithm validates a YAML document against a predefined schema. It recursively traverses both the YAML data and the schema, checking for type consistency, required fields, and property existence. This is crucial for ensuring data integrity and preventing errors in applications that consume YAML configurations or data. For instance, it can verify that a user profile YAML file contains all necessary fields like 'name', 'email', and 'age' with the correct data types.

Algorithm explanation:

The `validate` method initiates a recursive validation process using `validateRecursive`. This helper function checks type compatibility between the data and the schema node, then proceeds based on the schema type (object, array, primitive). For objects, it verifies required properties and recursively validates defined properties, optionally checking for additional properties. For arrays, it recursively validates each item against the defined item schema. Edge cases include null data, missing schema nodes, type mismatches, missing required fields, and unexpected properties. The time complexity is O(N*S) in the worst case, where N is the number of nodes in the YAML data and S is the number of nodes in the schema, as each data node might be compared against schema nodes. Space complexity is O(D + S) for recursion depth (D) and schema storage (S).

Pseudocode:

FUNCTION validate(yamlData, schema):
  errors = empty list
  validateRecursive(yamlData, schema.root, "", errors)
  RETURN errors

FUNCTION validateRecursive(data, schemaNode, path, errors):
  IF schemaNode is null THEN add error "Schema definition error" to errors; RETURN

  IF NOT isTypeMatch(data, schemaNode.type) THEN
    add error "Type mismatch" to errors
    RETURN

  IF data is null THEN RETURN

  SWITCH schemaNode.type:
    CASE "object":
      FOR EACH requiredProp in schemaNode.requiredProperties:
        IF dataMap does not contain requiredProp THEN add error "Missing required property" to errors
      FOR EACH key, value in dataMap:
        propertySchema = schemaNode.getPropertySchema(key)
        IF propertySchema is not null THEN
          validateRecursive(value, propertySchema, path + "." + key, errors)
        ELSE IF NOT schemaNode.allowAdditionalProperties THEN
          add error "Unexpected property" to errors
    CASE "array":
      itemsSchema = schemaNode.getItemsSchema()
      IF itemsSchema is not null THEN
        FOR i FROM 0 TO dataList.size - 1:
          validateRecursive(dataList[i], itemsSchema, path + "[" + i + "]", errors)
    // ... handle other types like string, integer, boolean ...

FUNCTION isTypeMatch(data, schemaType):
  IF data is null THEN RETURN true
  SWITCH schemaType:
    CASE "object": RETURN data is Map
    CASE "array": RETURN data is List
    // ... handle other types ...
  RETURN false