JSON Schema Validator (cpp, written by Claude Code)
envgap__claude-code__cpp-t1-2
Written by a coding agent; not on GitHubWritten 2026-02-27
01 / FAILURE SIGNATURE
As the study recorded it
No identifying execution failure has been captured.
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
CMakeLists.txt- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
claude-code/cpp-t1 #2 · read the task the agent was given
Claude Code wrote this cpp project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: JSON Schema Validator Write a program that validates JSON documents against user-defined schema rules. It should support type checking, required fields, nested object validation, array constraints, and pattern matching. It should collect all violations — not stop at the first — and produce a detailed validation report. FUNCTIONAL REQUIREMENTS: - Accept two command-line arguments: a JSON data file and a JSON schema file - Support validation rules: type checking (string, number, boolean, array, object, null), required fields, min/max for numbers, minLength/maxLength for strings, enum values, regex pattern matching - Validate nested objects and arrays recursively to any depth - Validate array items (all items must conform to a specified type or sub-schema) - Collect ALL validation errors across the entire document, reporting the full JSON path for each violation (e.g., $.users[2].email) - Print the validation report to the console with one line per violation showing path, expected rule, and actual value - Save the validation report as validation_report.json with structured error objects - If no input files are given, generate a sample schema and a sample data file with intentional violations across different rule types, then validate - Handle malformed JSON input gracefully with clear error messages distinguishing parse errors from validation errors Create a complete C++ project for a clean Ubuntu 22.04 machine with only G++ 12+ and CMake 3.22+ installed. Include: - Source code - CMakeLists.txt with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(json_schema_validator_trial1 VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
# nlohmann/json v3.11.3
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(nlohmann_json)
# valijson v1.0.2
FetchContent_Declare(
valijson
GIT_REPOSITORY https://github.com/tristanpenman/valijson.git
GIT_TAG v1.0.2
)
set(valijson_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(valijson_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(valijson)
add_executable(validator validator.cpp)
target_link_libraries(validator PRIVATE nlohmann_json::nlohmann_json valijson)
target_include_directories(validator PRIVATE ${valijson_SOURCE_DIR}/include)
README.md
# JSON Schema Validator - C++ Trial 1 ## Dependencies - **nlohmann/json** (3.11.3): JSON for Modern C++ - **valijson** (1.0.2): Header-only JSON Schema validation library ## Build ```bash mkdir build && cd build cmake .. cmake --build . ``` ## Usage ```bash # Validate a JSON file against a schema ./validator data.json schema.json # Generate sample files with intentional violations ./validator ``` ## Output - Console report with all violations and JSON paths - `validation_report.json` with structured error details
validator.cpp
/**
* JSON Schema Validator - C++ Trial 1
* Uses nlohmann/json for JSON parsing and valijson for JSON Schema validation.
* Validates JSON documents and produces detailed reports with JSON paths.
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <nlohmann/json.hpp>
#include <valijson/adapters/nlohmann_json_adapter.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validation_results.hpp>
#include <valijson/validator.hpp>
using json = nlohmann::json;
using valijson::Schema;
using valijson::SchemaParser;
using valijson::Validator;
using valijson::ValidationResults;
using valijson::adapters::NlohmannJsonAdapter;
struct ErrorEntry {
std::string path;
std::string message;
std::string validator;
std::string value;
};
// --- Sample Data and Schema ---
json generateSampleData() {
return json::parse(R"({
"users": [
{
"id": 1,
"name": "Alice Johnson",
"email": "alice@example.com",
"age": 30,
"role": "admin",
"address": {
"street": "123 Main St",
"city": "Springfield",
"zip": "62701"
}
},
{
"id": "not-a-number",
"name": "",
"email": "invalid-email",
"age": -5,
"role": "superuser",
"address": {
"street": "",
"city": 12345,
"zip": "ABC"
}
},
{
"id": 3,
"age": 200,
"role": "viewer",
"address": {
"street": "789 Oak Ave",
"city": "Shelbyville"
}
}
],
"metadata": {
"version": 2.5,
"tags": ["production", 42, "stable"],
"created": "2024-01-15"
},
"active": "yes"
})");
}
json generateSampleSchema() {
return json::parse(R"({
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User Database",
"type": "object",
"required": ["users", "metadata", "active"],
"properties": {
"users": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["id", "name", "email", "age", "role", "address"],
"properties": {
"id": {"type": "integer", "minimum": 1},
"name": {"type": "string", "minLength": 1, "maxLength": 100},
"email": {"type": "string", "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"},
"age": {"type": "integer", "minimum": 0, "maximum": 150},
"role": {"type": "string", "enum": ["admin", "editor", "viewer"]},
"address": {
"type": "object",
"required": ["street", "city", "zip"],
"properties": {
"street": {"type": "string", "minLength": 1},
"city": {"type": "string", "minLength": 1},
"zip": {"type": "string", "pattern": "^[0-9]{5}(-[0-9]{4})?$"}
}
}
}
}
},
"metadata": {
"type": "object",
"required": ["version", "tags"],
"properties": {
"version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
"tags": {
"type": "array",
"items": {"type": "string", "minLength": 1},
"minItems": 1
}
}
},
"active": {"type": "boolean"}
}
})");
}
// --- Utilities ---
std::string getCurrentTimestamp() {
auto now = std::chrono::system_clock::now();
auto time_t = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &time_t);
#else
localtime_r(&time_t, &tm_buf);
#endif
std::ostringstream oss;
oss << std::put_time(&tm_buf, "%Y-%m-%dT%H:%M:%S");
return oss.str();
}
json loadJsonFile(const std::string& filepath) {
std::ifstream file(filepath);
if (!file.is_open()) {
std::cerr << "Error: File not found: " << filepath << std::endl;
exit(1);
}
try {
json data;
file >> data;
return data;
} catch (const json::parse_error& e) {
std::cerr << "Error: Malformed JSON in " << filepath << std::endl;
std::cerr << " " << e.what() << std::endl;
exit(1);
}
}
void writeJsonFile(const std::string& filepath, const json& data) {
std::ofstream file(filepath);
if (!file.is_open()) {
std::cerr << "Error: Cannot write to " << filepath << std::endl;
return;
}
file << data.dump(2);
}
// --- Validation ---
std::vector<ErrorEntry> validate(const json& data, const json& schemaJson) {
std::vector<ErrorEntry> errors;
Schema schema;
SchemaParser parser;
NlohmannJsonAdapter schemaAdapter(schemaJson);
try {
parser.populateSchema(schemaAdapter, schema);
} catch (const std::exception& e) {
errors.push_back({"$", std::string("Schema error: ") + e.what(), "schema", "N/A"});
return errors;
}
Validator validator;
ValidationResults results;
NlohmannJsonAdapter dataAdapter(data);
if (!validator.validate(schema, dataAdapter, &results)) {
ValidationResults::Error error;
while (results.popError(error)) {
// Build JSON path from context
std::string path = "$";
for (const auto& contextElement : error.context) {
std::string elem = contextElement;
if (!elem.empty()) {
// Remove leading '<' and trailing '>' if present
if (elem.front() == '<' && elem.back() == '>') {
elem = elem.substr(1, elem.size() - 2);
}
// Check if it's an array index
bool isNumber = !elem.empty();
for (char c : elem) {
if (!std::isdigit(c)) {
isNumber = false;
break;
}
}
if (isNumber) {
path += "[" + elem + "]";
} else if (!elem.empty()) {
if (path != "$") {
path += "." + elem;
} else {
path += "." + elem;
}
}
}
}
errors.push_back({
path,
error.description,
"valijson",
"N/A"
});
}
}
return errors;
}
// --- Reporting ---
void printReport(const std::vector<ErrorEntry>& errors, const std::string& dataFile, const std::string& schemaFile) {
std::string sep(70, '=');
std::string sep2(70, '-');
std::string timestamp = getCurrentTimestamp();
std::cout << sep << std::endl;
std::cout << "JSON SCHEMA VALIDATION REPORT" << std::endl;
std::cout << sep << std::endl;
std::cout << " Data file: " << dataFile << std::endl;
std::cout << " Schema file: " << schemaFile << std::endl;
std::cout << " Timestamp: " << timestamp << std::endl;
std::cout << sep2 << std::endl;
if (errors.empty()) {
std::cout << "\n RESULT: VALID - No violations found.\n" << std::endl;
} else {
std::cout << "\n RESULT: INVALID - " << errors.size() << " violation(s) found.\n" << std::endl;
std::cout << sep2 << std::endl;
for (size_t i = 0; i < errors.size(); ++i) {
const auto& err = errors[i];
std::cout << "\n Violation #" << (i + 1) << std::endl;
std::cout << " Path: " << err.path << std::endl;
std::cout << " Validator: " << err.validator << std::endl;
std::cout << " Message: " << err.message << std::endl;
if (err.value != "N/A") {
std::cout << " Value: " << err.value << std::endl;
}
}
}
std::cout << "\n" << sep << std::endl;
}
void saveReport(const std::vector<ErrorEntry>& errors, const std::string& dataFile, const std::string& schemaFile, const std::string& outputPath) {
json report;
report["timestamp"] = getCurrentTimestamp();
report["data_file"] = dataFile;
report["schema_file"] = schemaFile;
report["valid"] = errors.empty();
report["error_count"] = errors.size();
json errArray = json::array();
for (const auto& err : errors) {
json errObj;
errObj["path"] = err.path;
errObj["message"] = err.message;
errObj["validator"] = err.validator;
errObj["value"] = err.value;
errArray.push_back(errObj);
}
report["errors"] = errArray;
writeJsonFile(outputPath, report);
std::cout << " Report saved to: " << outputPath << std::endl;
}
// --- Main ---
int main(int argc, char* argv[]) {
std::string dataFile, schemaFile;
json data, schema;
if (argc == 3) {
dataFile = argv[1];
schemaFile = argv[2];
data = loadJsonFile(dataFile);
schema = loadJsonFile(schemaFile);
} else if (argc == 1) {
std::cout << "No input files provided. Generating sample data and schema...\n" << std::endl;
data = generateSampleData();
schema = generateSampleSchema();
dataFile = "sample_data.json";
schemaFile = "sample_schema.json";
writeJsonFile(dataFile, data);
writeJsonFile(schemaFile, schema);
std::cout << " Generated: " << dataFile << std::endl;
std::cout << " Generated: " << schemaFile << "\n" << std::endl;
} else {
std::cout << "Usage: validator <data.json> <schema.json>" << std::endl;
std::cout << " validator (generates sample files)" << std::endl;
return 1;
}
auto errors = validate(data, schema);
printReport(errors, dataFile, schemaFile);
saveReport(errors, dataFile, schemaFile, "validation_report.json");
return errors.empty() ? 0 : 1;
}