Source
stdlib/parsers/json/schema.hpp
1
// Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).2
// Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.3
#pragma once5
// cheatah::parsers::json — compile-time SCHEMA for reading JSON straight into user structs.6
//7
// A struct opts in NON-INTRUSIVELY by specializing the `schema<T>` variable template with an8
// `object(field(...), ...)` description — no base class, no macro, no member function, so it works9
// for third-party / aggregate types you cannot edit:10
//11
// struct Ohlc { std::string date; double open; double close; };12
// template<> inline constexpr auto schema<Ohlc> = object(13
// field("date", &Ohlc::date),14
// field("open", &Ohlc::open),15
// field("close", &Ohlc::close));16
//17
// read.hpp consumes this at compile time to parse directly into the fields (no Node/variant DOM).18
// Fully static; no runtime polymorphism.20
#include <string_view>21
#include <tuple>22
#include <type_traits>24
namespace cheatah::parsers::json {26
/**27
* @brief One mapping from a JSON object key to a struct data member (a key name plus a28
* pointer-to-member).29
* @tparam Class the struct type owning the member.30
* @tparam Member the member's value type.31
*/32
template <class Class, class Member>33
struct Field {34
std::string_view name; ///< the JSON object key this field maps to.35
Member Class::*ptr; ///< pointer to the target data member of @p Class.36
using class_type = Class; ///< the struct type owning the member.37
using member_type = Member; ///< the member's value type.38
};40
/**41
* Build one key->member mapping.42
* @tparam Class the struct type owning the member.43
* @tparam Member the member's value type.44
* @param name the JSON object key.45
* @param ptr pointer to the target data member.46
* @return the Field mapping.47
* @complexity O(1) — constexpr aggregate construction.48
* @alloc none.49
* @test CheatahParsers.SchemaFactoriesAtRuntime50
*/51
template <class Class, class Member>52
constexpr Field<Class, Member> field(std::string_view name, Member Class::*ptr) noexcept {53
return Field<Class, Member>{name, ptr};54
}56
/**57
* @brief A struct's schema: an ordered list of Fields. Declaration order is cosmetic — at parse58
* time each JSON key is matched to a field BY NAME, so the JSON's key order does not matter.59
* @tparam Fields the Field types making up the schema.60
*/61
template <class... Fields>62
struct ObjectSchema {63
std::tuple<Fields...> fields; ///< the field mappings, held as a tuple.64
};66
/**67
* Bundle fields into a schema.68
* @tparam Fields the Field types making up the schema.69
* @param fs the field mappings, in declaration order (cosmetic — matching is by name).70
* @return the ObjectSchema.71
* @complexity O(1) — constexpr tuple construction.72
* @alloc none.73
* @test CheatahParsers.SchemaFactoriesAtRuntime74
*/75
template <class... Fields>76
constexpr ObjectSchema<Fields...> object(Fields... fs) noexcept {77
return ObjectSchema<Fields...>{std::tuple<Fields...>{fs...}};78
}80
// Sentinel type for "this T has no schema". The primary template yields it; a user gives T a schema81
// by specializing: `template<> inline constexpr auto schema<Foo> = object(...);`.82
struct no_schema {};83
template <class T>84
inline constexpr no_schema schema{};86
// True iff T has a user-declared schema specialization (so read<>() treats it as a JSON object).87
template <class T>88
concept HasSchema = !std::is_same_v<std::remove_cvref_t<decltype(schema<T>)>, no_schema>;90
} // namespace cheatah::parsers::json