DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
json.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file json.h
6 * @brief Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.
7 *
8 * A deliberately small JSON helper for the common IoT shapes (a flat-ish object
9 * of strings / numbers / booleans, with bounded nesting). It allocates nothing:
10 * the writer formats into a caller-provided buffer, and the reader scans a
11 * NUL-terminated body in place. ArduinoJson remains the option when you need a
12 * full DOM - it heap-allocates, which this library avoids.
13 *
14 * ## Writing
15 * @code
16 * char buf[128];
17 * JsonWriter w(buf, sizeof(buf));
18 * w.begin_object();
19 * w.kv_str("status", "ok");
20 * w.kv_int("count", 3);
21 * w.key("items"); w.begin_array();
22 * w.str("a"); w.str("b");
23 * w.end_array();
24 * w.end_object();
25 * if (w.ok()) server.send(slot, 200, "application/json", w.c_str());
26 * // -> {"status":"ok","count":3,"items":["a","b"]}
27 * @endcode
28 *
29 * ## Reading (top-level keys of an object body)
30 * @code
31 * char ssid[33];
32 * if (json_get_str(req->body, "ssid", ssid, sizeof(ssid))) { ... }
33 * long port;
34 * if (json_get_int(req->body, "port", &port)) { ... }
35 * @endcode
36 */
37
38#ifndef DETERMINISTICESPASYNCWEBSERVER_JSON_H
39#define DETERMINISTICESPASYNCWEBSERVER_JSON_H
40
41#include "ServerConfig.h"
42#include <stddef.h>
43#include <stdint.h>
44
45/**
46 * @class JsonWriter
47 * @brief Builds a JSON document into a fixed caller buffer, no heap.
48 *
49 * Commas, key quoting, and string escaping are emitted automatically. On buffer
50 * overflow or a structural error (nesting past JSON_MAX_DEPTH), writing stops
51 * and ok() returns false; c_str() still yields a NUL-terminated (truncated)
52 * string so a partial result never runs off the end.
53 *
54 * Value methods (str(), integer(), ...) emit a single value - use them for array
55 * elements or immediately after key(). The kv_*() helpers emit a key and value
56 * together for object members.
57 */
59{
60 public:
61 /**
62 * @brief Construct over a caller buffer.
63 * @param buf Destination (must be non-null, cap >= 1).
64 * @param cap Capacity in bytes including the NUL terminator.
65 */
66 JsonWriter(char *buf, size_t cap);
67
68 void begin_object(); ///< Open `{` (as a value/element where applicable).
69 void end_object(); ///< Close `}`.
70 void begin_array(); ///< Open `[`.
71 void end_array(); ///< Close `]`.
72
73 /// @brief Emit an object member name (`"k":`); follow with one value.
74 void key(const char *k);
75
76 void str(const char *v); ///< Emit a quoted, escaped string value.
77 void integer(long v); ///< Emit a signed integer value.
78 void uinteger(unsigned long v); ///< Emit an unsigned integer value.
79 void boolean(bool v); ///< Emit `true`/`false`.
80 void null_value(); ///< Emit `null`.
81 void raw(const char *literal); ///< Emit a pre-formatted literal verbatim.
82
83 void kv_str(const char *k, const char *v); ///< `"k":"v"` (escaped).
84 void kv_int(const char *k, long v); ///< `"k":<int>`.
85 void kv_uint(const char *k, unsigned long v); ///< `"k":<uint>`.
86 void kv_bool(const char *k, bool v); ///< `"k":true|false`.
87 void kv_null(const char *k); ///< `"k":null`.
88 void kv_raw(const char *k, const char *literal); ///< `"k":<literal>`.
89
90 bool ok() const ///< False after any overflow / structural error.
91 {
92 return _ok;
93 }
94 size_t length() const ///< Bytes written so far (excludes the NUL).
95 {
96 return _len;
97 }
98 const char *c_str() const ///< NUL-terminated output (truncated if !ok()).
99 {
100 return _buf;
101 }
102
103 private:
104 void put(char c);
105 void put_raw(const char *s);
106 void put_escaped(const char *s);
107 void value_prefix(); // emit a separating comma at the current level if needed
108 void push(char open);
109 void pop(char close);
110
111 char *_buf;
112 size_t _cap;
113 size_t _len;
114 bool _ok;
115 bool _after_key; // next value follows a key(): suppress its comma
116 uint8_t _depth; // open containers
117 bool _need_comma[JSON_MAX_DEPTH]; // per-level: has a prior item been emitted?
118};
119
120/**
121 * @brief Read a top-level string member from a JSON object body.
122 *
123 * Finds `"key": "..."` at the root object level (nested objects/arrays and
124 * string contents are skipped, so a same-named nested key is not matched),
125 * unescapes the value, and copies it (NUL-terminated, bounded by @p out_cap)
126 * into @p out.
127 *
128 * @param json NUL-terminated JSON object text.
129 * @param key Member name to find.
130 * @param out Destination buffer.
131 * @param out_cap Capacity of @p out including the NUL.
132 * @return true if a string member was found and copied; false otherwise.
133 */
134bool json_get_str(const char *json, const char *key, char *out, size_t out_cap);
135
136/**
137 * @brief Read a top-level integer member from a JSON object body.
138 * @return true if the member exists and parses as an integer; false otherwise.
139 */
140bool json_get_int(const char *json, const char *key, long *out);
141
142/**
143 * @brief Read a top-level boolean member (`true`/`false`) from a JSON object body.
144 * @return true if the member exists and is a JSON boolean; false otherwise.
145 */
146bool json_get_bool(const char *json, const char *key, bool *out);
147
148#endif // DETERMINISTICESPASYNCWEBSERVER_JSON_H
User-facing configuration for DeterministicESPAsyncWebServer.
#define JSON_MAX_DEPTH
Maximum object/array nesting depth for the JsonWriter (see json.h).
Builds a JSON document into a fixed caller buffer, no heap.
Definition json.h:59
void str(const char *v)
Emit a quoted, escaped string value.
Definition json.cpp:171
void begin_object()
Open { (as a value/element where applicable).
Definition json.cpp:144
void key(const char *k)
Emit an object member name ("k":); follow with one value.
Definition json.cpp:161
void raw(const char *literal)
Emit a pre-formatted literal verbatim.
Definition json.cpp:207
void kv_bool(const char *k, bool v)
"k":true|false.
Definition json.cpp:228
void end_array()
Close ].
Definition json.cpp:156
void kv_str(const char *k, const char *v)
"k":"v" (escaped).
Definition json.cpp:213
void boolean(bool v)
Emit true/false.
Definition json.cpp:195
void integer(long v)
Emit a signed integer value.
Definition json.cpp:179
void kv_uint(const char *k, unsigned long v)
"k":<uint>.
Definition json.cpp:223
bool ok() const
< False after any overflow / structural error.
Definition json.h:90
void kv_int(const char *k, long v)
"k":<int>.
Definition json.cpp:218
void uinteger(unsigned long v)
Emit an unsigned integer value.
Definition json.cpp:187
void end_object()
Close }.
Definition json.cpp:148
size_t length() const
< Bytes written so far (excludes the NUL).
Definition json.h:94
void kv_raw(const char *k, const char *literal)
"k":<literal>.
Definition json.cpp:238
void null_value()
Emit null.
Definition json.cpp:201
void kv_null(const char *k)
"k":null.
Definition json.cpp:233
void begin_array()
Open [.
Definition json.cpp:152
const char * c_str() const
< NUL-terminated output (truncated if !ok()).
Definition json.h:98
bool json_get_str(const char *json, const char *key, char *out, size_t out_cap)
Read a top-level string member from a JSON object body.
Definition json.cpp:512
bool json_get_bool(const char *json, const char *key, bool *out)
Read a top-level boolean member (true/false) from a JSON object body.
Definition json.cpp:567
bool json_get_int(const char *json, const char *key, long *out)
Read a top-level integer member from a JSON object body.
Definition json.cpp:552