Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5453995

Browse files
committed
Backward-compatible refactoring of the Json and MessagePack integration .
This PR: - refactors the macros to activate or not Json and MessagePack support - regroups the code for both since it is similar in many ways - add deprecations where applicable - add the ability to easily add a JsonVariant callback with `server.on("/testJsonPost", HTTP_POST, [](AsyncWebServerRequest *request, JsonVariant &json)` - Improve examples This PR is tested.
1 parent 0951505 commit 5453995

File tree

10 files changed

+176
-303
lines changed

10 files changed

+176
-303
lines changed

examples/ChunkRetryResponse/ChunkRetryResponse.ino

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@
1919

2020
#include <ESPAsyncWebServer.h>
2121

22-
#if __has_include("ArduinoJson.h")
23-
#include <ArduinoJson.h>
24-
#include <AsyncJson.h>
25-
#include <AsyncMessagePack.h>
26-
#endif
27-
2822
static const char *htmlContent PROGMEM = R"(
2923
<!DOCTYPE html>
3024
<html>
@@ -107,7 +101,7 @@ void setup() {
107101

108102
server.addMiddleware(&requestLogger);
109103

110-
#if __has_include("ArduinoJson.h")
104+
#if ASYNC_JSON_SUPPORT == 1
111105

112106
//
113107
// HOW TO RUN THIS EXAMPLE:

examples/Json/Json.ino

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,9 @@
1919

2020
#include <ESPAsyncWebServer.h>
2121

22-
#if __has_include("ArduinoJson.h")
23-
#include <ArduinoJson.h>
24-
#include <AsyncJson.h>
25-
#include <AsyncMessagePack.h>
26-
#endif
27-
2822
static AsyncWebServer server(80);
2923

30-
#if __has_include("ArduinoJson.h")
24+
#if ASYNC_JSON_SUPPORT == 1
3125
static AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/json2");
3226
#endif
3327

@@ -39,7 +33,7 @@ void setup() {
3933
WiFi.softAP("esp-captive");
4034
#endif
4135

42-
#if __has_include("ArduinoJson.h")
36+
#if ASYNC_JSON_SUPPORT == 1
4337
//
4438
// sends JSON using AsyncJsonResponse
4539
//
@@ -92,6 +86,20 @@ void setup() {
9286
});
9387

9488
server.addHandler(handler);
89+
90+
// New Json API since 3.8.2, which works for both Json and MessagePack bodies
91+
// curl -v -X POST -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/json3
92+
93+
server.on("/json3", HTTP_POST, [](AsyncWebServerRequest *request, JsonVariant &json) {
94+
Serial.printf("Body request : ");
95+
serializeJson(json, Serial);
96+
Serial.println();
97+
AsyncJsonResponse *response = new AsyncJsonResponse();
98+
JsonObject root = response->getRoot().to<JsonObject>();
99+
root["hello"] = json.as<JsonObject>()["name"];
100+
response->setLength();
101+
request->send(response);
102+
});
95103
#endif
96104

97105
server.begin();

examples/MessagePack/MessagePack.ino

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,10 @@
1919

2020
#include <ESPAsyncWebServer.h>
2121

22-
#if __has_include("ArduinoJson.h")
23-
#include <ArduinoJson.h>
24-
#include <AsyncJson.h>
25-
#include <AsyncMessagePack.h>
26-
#endif
27-
2822
static AsyncWebServer server(80);
2923

30-
#if __has_include("ArduinoJson.h")
31-
static AsyncCallbackMessagePackWebHandler *handler = new AsyncCallbackMessagePackWebHandler("/msgpack2");
24+
#if ASYNC_JSON_SUPPORT == 1
25+
static AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/msgpack2");
3226
#endif
3327

3428
void setup() {
@@ -39,7 +33,7 @@ void setup() {
3933
WiFi.softAP("esp-captive");
4034
#endif
4135

42-
#if __has_include("ArduinoJson.h")
36+
#if ASYNC_JSON_SUPPORT == 1
4337
//
4438
// sends MessagePack using AsyncMessagePackResponse
4539
//
@@ -57,18 +51,26 @@ void setup() {
5751
//
5852
// curl -v http://192.168.4.1/msgpack2
5953
//
54+
// Save file: curl -v http://192.168.4.1/msgpack2 -o msgpack.bin
55+
//
6056
server.on("/msgpack2", HTTP_GET, [](AsyncWebServerRequest *request) {
6157
AsyncResponseStream *response = request->beginResponseStream("application/msgpack");
6258
JsonDocument doc;
6359
JsonObject root = doc.to<JsonObject>();
64-
root["foo"] = "bar";
60+
root["name"] = "Bob";
6561
serializeMsgPack(root, *response);
6662
request->send(response);
6763
});
6864

65+
// POST file:
66+
//
67+
// curl -v -X POST -H 'Content-Type: application/msgpack' --data-binary @msgpack.bin http://192.168.4.1/msgpack2
68+
//
6969
handler->setMethod(HTTP_POST | HTTP_PUT);
7070
handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
71+
Serial.printf("Body request /msgpack2 : "); // should print: Body request /msgpack2 : {"name":"Bob"}
7172
serializeJson(json, Serial);
73+
Serial.println();
7274
AsyncMessagePackResponse *response = new AsyncMessagePackResponse();
7375
JsonObject root = response->getRoot().to<JsonObject>();
7476
root["hello"] = json.as<JsonObject>()["name"];
@@ -77,6 +79,22 @@ void setup() {
7779
});
7880

7981
server.addHandler(handler);
82+
83+
// New Json API since 3.8.2, which works for both Json and MessagePack bodies
84+
//
85+
// curl -v -X POST -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/msgpack3
86+
// curl -v -X POST -H 'Content-Type: application/msgpack' --data-binary @msgpack.bin http://192.168.4.1/msgpack3
87+
//
88+
server.on("/msgpack3", HTTP_POST, [](AsyncWebServerRequest *request, JsonVariant &json) {
89+
Serial.printf("Body request /msgpack3 : "); // should print: Body request /msgpack3 : {"name":"Bob"}
90+
serializeJson(json, Serial);
91+
Serial.println();
92+
AsyncJsonResponse *response = new AsyncJsonResponse();
93+
JsonObject root = response->getRoot().to<JsonObject>();
94+
root["hello"] = json.as<JsonObject>()["name"];
95+
response->setLength();
96+
request->send(response);
97+
});
8098
#endif
8199

82100
server.begin();

platformio.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ lib_compat_mode = strict
6666
lib_ldf_mode = chain
6767
lib_deps =
6868
bblanchon/ArduinoJson @ 7.4.2
69+
; bblanchon/ArduinoJson @ 6.21.5
70+
; bblanchon/ArduinoJson @ 5.13.4
6971
ESP32Async/AsyncTCP @ 3.4.9
7072
board_build.partitions = partitions-4MB.csv
7173
board_build.filesystem = littlefs

src/AsyncJson.cpp

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#if ASYNC_JSON_SUPPORT == 1
88

9+
// Json content type response classes
10+
911
#if ARDUINOJSON_VERSION_MAJOR == 5
1012
AsyncJsonResponse::AsyncJsonResponse(bool isArray) : _isValid{false} {
1113
_code = 200;
@@ -88,6 +90,27 @@ size_t PrettyAsyncJsonResponse::_fillBuffer(uint8_t *data, size_t len) {
8890
return len;
8991
}
9092

93+
// MessagePack content type response
94+
#if ASYNC_MSG_PACK_SUPPORT == 1
95+
96+
size_t AsyncMessagePackResponse::setLength() {
97+
_contentLength = measureMsgPack(_root);
98+
if (_contentLength) {
99+
_isValid = true;
100+
}
101+
return _contentLength;
102+
}
103+
104+
size_t AsyncMessagePackResponse::_fillBuffer(uint8_t *data, size_t len) {
105+
ChunkPrint dest(data, _sentLength, len);
106+
serializeMsgPack(_root, dest);
107+
return len;
108+
}
109+
110+
#endif
111+
112+
// Body handler supporting both content types: JSON and MessagePack
113+
91114
#if ARDUINOJSON_VERSION_MAJOR == 6
92115
AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(const String &uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize)
93116
: _uri(uri), _method(HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
@@ -105,11 +128,12 @@ bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) cons
105128
return false;
106129
}
107130

108-
if (request->method() != HTTP_GET && !request->contentType().equalsIgnoreCase(asyncsrv::T_application_json)) {
109-
return false;
110-
}
111-
112-
return true;
131+
#if ASYNC_MSG_PACK_SUPPORT == 1
132+
return request->method() == HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json)
133+
|| request->contentType().equalsIgnoreCase(asyncsrv::T_application_msgpack);
134+
#else
135+
return request->method() == HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json);
136+
#endif
113137
}
114138

115139
void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest *request) {
@@ -136,26 +160,32 @@ void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest *request)
136160
}
137161

138162
#if ARDUINOJSON_VERSION_MAJOR == 5
139-
DynamicJsonBuffer jsonBuffer;
140-
JsonVariant json = jsonBuffer.parse((const char *)request->_tempObject);
141-
if (json.success()) {
163+
DynamicJsonBuffer doc;
142164
#elif ARDUINOJSON_VERSION_MAJOR == 6
143-
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
144-
DeserializationError error = deserializeJson(jsonBuffer, (const char *)request->_tempObject);
145-
if (!error) {
146-
JsonVariant json = jsonBuffer.as<JsonVariant>();
165+
DynamicJsonDocument doc(this->maxJsonBufferSize);
147166
#else
148-
JsonDocument jsonBuffer;
149-
DeserializationError error = deserializeJson(jsonBuffer, (const char *)request->_tempObject);
150-
if (!error) {
151-
JsonVariant json = jsonBuffer.as<JsonVariant>();
167+
JsonDocument doc;
152168
#endif
153169

170+
#if ARDUINOJSON_VERSION_MAJOR == 5
171+
JsonVariant json = doc.parse((const char *)request->_tempObject);
172+
if (json.success()) {
154173
_onRequest(request, json);
155-
} else {
156-
// error parsing the body
157-
request->send(400);
174+
return;
175+
}
176+
#else
177+
DeserializationError error = request->contentType().equalsIgnoreCase(asyncsrv::T_application_msgpack)
178+
? deserializeMsgPack(doc, (uint8_t *)(request->_tempObject))
179+
: deserializeJson(doc, (const char *)request->_tempObject);
180+
if (!error) {
181+
JsonVariant json = doc.as<JsonVariant>();
182+
_onRequest(request, json);
183+
return;
158184
}
185+
#endif
186+
187+
// error parsing the body
188+
request->send(400);
159189
}
160190
}
161191

src/AsyncJson.h

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
11
// SPDX-License-Identifier: LGPL-3.0-or-later
22
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
33

4-
#ifndef ASYNC_JSON_H_
5-
#define ASYNC_JSON_H_
4+
#pragma once
65

7-
#if __has_include("ArduinoJson.h")
8-
#include <ArduinoJson.h>
9-
#if ARDUINOJSON_VERSION_MAJOR >= 5
10-
#define ASYNC_JSON_SUPPORT 1
11-
#else
12-
#define ASYNC_JSON_SUPPORT 0
13-
#endif // ARDUINOJSON_VERSION_MAJOR >= 5
14-
#endif // __has_include("ArduinoJson.h")
15-
16-
#if ASYNC_JSON_SUPPORT == 1
176
#include <ESPAsyncWebServer.h>
18-
197
#include "ChunkPrint.h"
208

9+
#if ASYNC_JSON_SUPPORT == 1
10+
2111
#if ARDUINOJSON_VERSION_MAJOR == 6
2212
#ifndef DYNAMIC_JSON_DOCUMENT_SIZE
2313
#define DYNAMIC_JSON_DOCUMENT_SIZE 1024
2414
#endif
2515
#endif
2616

17+
// Json content type response classes
18+
2719
class AsyncJsonResponse : public AsyncAbstractResponse {
2820
protected:
2921
#if ARDUINOJSON_VERSION_MAJOR == 5
@@ -49,11 +41,11 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
4941
bool _sourceValid() const {
5042
return _isValid;
5143
}
52-
size_t setLength();
44+
virtual size_t setLength();
5345
size_t getSize() const {
5446
return _jsonBuffer.size();
5547
}
56-
size_t _fillBuffer(uint8_t *data, size_t len);
48+
virtual size_t _fillBuffer(uint8_t *data, size_t len);
5749
#if ARDUINOJSON_VERSION_MAJOR >= 6
5850
bool overflowed() const {
5951
return _jsonBuffer.overflowed();
@@ -68,11 +60,31 @@ class PrettyAsyncJsonResponse : public AsyncJsonResponse {
6860
#else
6961
PrettyAsyncJsonResponse(bool isArray = false);
7062
#endif
71-
size_t setLength();
72-
size_t _fillBuffer(uint8_t *data, size_t len);
63+
size_t setLength() override;
64+
size_t _fillBuffer(uint8_t *data, size_t len) override;
7365
};
7466

75-
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> ArJsonRequestHandlerFunction;
67+
// MessagePack content type response
68+
#if ASYNC_MSG_PACK_SUPPORT == 1
69+
70+
class AsyncMessagePackResponse : public AsyncJsonResponse {
71+
public:
72+
#if ARDUINOJSON_VERSION_MAJOR == 6
73+
AsyncMessagePackResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse(isArray, maxJsonBufferSize) {
74+
_contentType = asyncsrv::T_application_msgpack;
75+
}
76+
#else
77+
AsyncMessagePackResponse(bool isArray = false) : AsyncJsonResponse(isArray) {
78+
_contentType = asyncsrv::T_application_msgpack;
79+
}
80+
#endif
81+
size_t setLength() override;
82+
size_t _fillBuffer(uint8_t *data, size_t len) override;
83+
};
84+
85+
#endif
86+
87+
// Body handler supporting both content types: JSON and MessagePack
7688

7789
class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
7890
protected:
@@ -114,5 +126,3 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
114126
};
115127

116128
#endif // ASYNC_JSON_SUPPORT == 1
117-
118-
#endif // ASYNC_JSON_H_

0 commit comments

Comments
 (0)