nfx-json 1.5.2
Modern C++20 JSON library with schema validation and generation
Loading...
Searching...
No Matches
SchemaValidator.h
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2026 nfx
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
32
33#pragma once
34
35#include "Document.h"
36
37#include <optional>
38#include <string>
39#include <string_view>
40#include <unordered_map>
41#include <vector>
42
43namespace nfx::json
44{
45 //=====================================================================
46 // ValidationError class
47 //=====================================================================
48
55 class ValidationError final
56 {
57 public:
65 {
66 std::string path;
67 std::string message;
68 std::string constraint;
69 std::string expectedValue = {};
70 std::string actualValue = {};
71 };
72
73 public:
74 //----------------------------------------------
75 // Construction
76 //----------------------------------------------
81 explicit ValidationError( const ErrorEntry& entry );
82
92 std::string path,
93 std::string message,
94 std::string constraint,
95 std::string expectedValue = {},
96 std::string actualValue = {} );
97
98 //----------------------------------------------
99 // Destruction
100 //----------------------------------------------
101
105 ~ValidationError() = default;
106
107 //----------------------------------------------
108 // Accessors
109 //----------------------------------------------
110
115 inline const std::string& path() const noexcept;
116
121 inline const std::string& message() const noexcept;
122
127 inline const std::string& constraint() const noexcept;
128
133 inline const std::string& expectedValue() const noexcept;
134
139 inline const std::string& actualValue() const noexcept;
140
145 std::string toString() const;
146
147 private:
148 ErrorEntry m_error;
149 };
150
151 //=====================================================================
152 // ValidationResult class
153 //=====================================================================
154
161 {
162 public:
163 //----------------------------------------------
164 // Construction
165 //----------------------------------------------
166
170 ValidationResult() = default;
171
176 explicit ValidationResult( std::vector<ValidationError> errors );
177
178 //----------------------------------------------
179 // Destruction
180 //----------------------------------------------
181
185 ~ValidationResult() = default;
186
187 //----------------------------------------------
188 // Status checking
189 //----------------------------------------------
190
195 inline bool isValid() const noexcept;
196
201 inline bool hasErrors() const noexcept;
202
207 inline size_t errorCount() const noexcept;
208
209 //----------------------------------------------
210 // Error access
211 //----------------------------------------------
212
217 inline const std::vector<ValidationError>& errors() const noexcept;
218
225 const ValidationError& error( size_t index ) const;
226
231 std::string errorSummary() const;
232
233 //----------------------------------------------
234 // Error manipulation
235 //----------------------------------------------
236
241 void addError( const ValidationError::ErrorEntry& entry );
242
248
258 std::string_view path,
259 std::string_view message,
260 std::string_view constraint,
261 std::string_view expectedValue = {},
262 std::string_view actualValue = {} );
263
264 private:
265 std::vector<ValidationError> m_errors;
266 };
267
268 //=====================================================================
269 // SchemaDraft enumeration
270 //=====================================================================
271
286
287 //=====================================================================
288 // SchemaValidator class
289 //=====================================================================
290
299 class SchemaValidator final
300 {
301 public:
302 //----------------------------------------------
303 // Options
304 //----------------------------------------------
305
309 struct Options
310 {
311 bool strictMode = false;
312 size_t maxDepth = 64;
313 };
314
315 //----------------------------------------------
316 // Construction
317 //----------------------------------------------
318
324
329 explicit SchemaValidator( const Document& schema );
330
337
343
348 SchemaValidator( SchemaValidator&& other ) noexcept;
349
350 //----------------------------------------------
351 // Destruction
352 //----------------------------------------------
353
358
359 //----------------------------------------------
360 // Assignment
361 //----------------------------------------------
362
369
376
377 //----------------------------------------------
378 // Schema management
379 //----------------------------------------------
380
386 bool load( const Document& schema );
387
393 bool load( std::string_view schemaJson );
394
399 bool hasSchema() const;
400
404 void clear();
405
411
412 //----------------------------------------------
413 // Validation operations
414 //----------------------------------------------
415
423 ValidationResult validate( const Document& document ) const;
424
434 const Document& document, std::string_view documentPath = "", std::string_view schemaPath = "" ) const;
435
436 //----------------------------------------------
437 // Schema information
438 //----------------------------------------------
439
444 std::string version() const;
445
451
456 std::string draftString() const;
457
462 std::string title() const;
463
468 std::string description() const;
469
474 const Options& options() const noexcept;
475
476 private:
477 //----------------------------------------------
478 // Internal validation methods
479 //----------------------------------------------
480
489 void validateNode(
490 const Document& document,
491 const Document& schema,
492 std::string_view path,
493 ValidationResult& result,
494 size_t currentDepth = 0 ) const;
495
496 void validateType(
497 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
498
499 void validateRequired(
500 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
501
502 void validateProperties(
503 const Document& document,
504 const Document& schema,
505 std::string_view path,
506 ValidationResult& result,
507 size_t currentDepth = 0 ) const;
508
509 void validateNumericConstraints(
510 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
511
512 void validateStringConstraints(
513 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
514
515 void validateEnum(
516 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
517
518 void validateConst(
519 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
520
521 void validateAdditionalProperties(
522 const Document& document, const Document& schema, std::string_view path, ValidationResult& result ) const;
523
524 void validateObject(
525 const Document& document,
526 const Document& schema,
527 std::string_view path,
528 ValidationResult& result,
529 size_t currentDepth = 0 ) const;
530
531 void validateArray(
532 const Document& document,
533 const Document& schema,
534 std::string_view path,
535 ValidationResult& result,
536 size_t currentDepth = 0 ) const;
537
538 void validateAllOf(
539 const Document& document,
540 const Document& schema,
541 std::string_view path,
542 ValidationResult& result,
543 size_t currentDepth = 0 ) const;
544
545 void validateAnyOf(
546 const Document& document,
547 const Document& schema,
548 std::string_view path,
549 ValidationResult& result,
550 size_t currentDepth = 0 ) const;
551
552 void validateOneOf(
553 const Document& document,
554 const Document& schema,
555 std::string_view path,
556 ValidationResult& result,
557 size_t currentDepth = 0 ) const;
558
559 void validateNot(
560 const Document& document,
561 const Document& schema,
562 std::string_view path,
563 ValidationResult& result,
564 size_t currentDepth = 0 ) const;
565
566 void validateIfThenElse(
567 const Document& document,
568 const Document& schema,
569 std::string_view path,
570 ValidationResult& result,
571 size_t currentDepth = 0 ) const;
572
573 //----------------------------------------------
574 // Helper methods
575 //----------------------------------------------
576
577 bool referenceExists( std::string_view reference ) const noexcept;
578 Document resolveReference( std::string_view reference ) const;
579 std::string actualType( const Document& document, std::string_view path ) const noexcept;
580 Document extractSubDocument( const Document& sourceDocument, std::string_view path ) const;
581 void buildAnchorIndex();
582 void scanForAnchors( const Document& schema, const std::string& currentPath );
583 void detectDraft();
584 std::string draftToString() const noexcept;
585
586 //----------------------------------------------
587 // Member variables
588 //----------------------------------------------
589
590 static constexpr size_t DEFAULT_MAX_DEPTH = 64;
591
592 Document m_schema;
593 bool m_schemaLoaded = false;
594 bool m_strictMode = false;
595 size_t m_maxDepth = DEFAULT_MAX_DEPTH;
596 SchemaDraft m_schemaDraft = SchemaDraft::Unknown;
597 mutable std::unordered_map<std::string, Document> m_refCache;
598 std::unordered_map<std::string, std::string> m_anchorIndex;
599 };
600} // namespace nfx::json
601
602#include "detail/SchemaValidator.inl"
SchemaDraft
Enumeration of supported JSON Schema draft versions.
@ Draft04
JSON Schema Draft 4.
@ Draft201909
JSON Schema Draft 2019-09.
@ Draft07
JSON Schema Draft 7.
@ Draft202012
JSON Schema Draft 2020-12 (current).
@ Unknown
Schema draft version is not recognized or not specified.
@ Draft06
JSON Schema Draft 6.
JSON Document type with low-level and high-level APIs.
Low-level JSON value storage type.
Definition Document.h:108
Represents a single JSON schema validation error.
ValidationError(std::string path, std::string message, std::string constraint, std::string expectedValue={}, std::string actualValue={})
Construct validation error.
const std::string & path() const noexcept
Get the JSON path where validation failed.
~ValidationError()=default
Destructor.
const std::string & expectedValue() const noexcept
Get expected value or constraint.
std::string toString() const
Get formatted error string.
ValidationError(const ErrorEntry &entry)
Construct validation error from ErrorEntry struct.
const std::string & constraint() const noexcept
Get the constraint type that failed.
const std::string & message() const noexcept
Get human-readable error message.
const std::string & actualValue() const noexcept
Get actual value found in document.
Simple error entry structure for convenient ValidationError construction.
std::string actualValue
Actual value found in document.
std::string constraint
Schema constraint that failed.
std::string expectedValue
Expected value or constraint.
std::string path
JSON path where error occurred.
std::string message
Human-readable error message.
Result of JSON schema validation operation.
const ValidationError & error(size_t index) const
Get validation error by index.
bool hasErrors() const noexcept
Check if validation failed.
~ValidationResult()=default
Destructor.
ValidationResult()=default
Construct successful validation result.
ValidationResult(std::vector< ValidationError > errors)
Construct validation result with errors.
std::string errorSummary() const
Get formatted error summary.
bool isValid() const noexcept
Check if validation was successful.
size_t errorCount() const noexcept
Get number of validation errors.
const std::vector< ValidationError > & errors() const noexcept
Get all validation errors.
void addError(const ValidationError::ErrorEntry &entry)
Add validation error from ErrorEntry.
std::string draftString() const
Get schema draft version as human-readable string.
std::string version() const
Get schema version/draft URI.
SchemaValidator(SchemaValidator &&other) noexcept
Move constructor.
ValidationResult validate(const Document &document) const
Validate Document against loaded schema.
SchemaValidator(const Document &schema)
Construct validator with schema (default options).
SchemaValidator & operator=(SchemaValidator &&other) noexcept
Move assignment operator.
const Options & options() const noexcept
Get validation options.
SchemaValidator()
Default constructor - creates empty validator.
bool hasSchema() const
Check if validator has valid schema loaded.
SchemaValidator(const Document &schema, const Options &options)
Construct validator with schema.
SchemaValidator & operator=(const SchemaValidator &other)
Copy assignment operator.
SchemaDraft draft() const
Get detected JSON Schema draft version.
void clear()
Clear loaded schema.
bool load(const Document &schema)
Load JSON schema from Document.
bool load(std::string_view schemaJson)
Load JSON schema from string.
ValidationResult validateAtPath(const Document &document, std::string_view documentPath="", std::string_view schemaPath="") const
Validate Document at specific path against schema.
SchemaValidator(const SchemaValidator &other)
Copy constructor.
std::string description() const
Get schema description.
Document schema() const
Get current schema as Document.
std::string title() const
Get schema title.
Configuration options for validation.
size_t maxDepth
Maximum recursion depth (0 = unlimited).
bool strictMode
If true, unknown properties cause validation failure.