Skip to content
This repository was archived by the owner on Mar 5, 2026. It is now read-only.

Commit d7399a7

Browse files
avonwyssme-no-dev
authored andcommitted
Added handler for correct JSON deserialization, addresses me-no-dev#195 (me-no-dev#287)
* Added handler for correct JSON deserialization (even with multiple body data writes), addresses me-no-dev#195 * Fixed typo * Added JSON handler example to readme * Moved Json Handler uri parameter to constructor * Use request->_tempObject for JSON char data buffer * Moved onRequest to constructor in JSON async handler
1 parent fc66fae commit d7399a7

2 files changed

Lines changed: 99 additions & 4 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ To use this library you might need to have the latest git versions of [ESP32](ht
3030
- [GET, POST and FILE parameters](#get-post-and-file-parameters)
3131
- [FILE Upload handling](#file-upload-handling)
3232
- [Body data handling](#body-data-handling)
33+
- [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson)
3334
- [Responses](#responses)
3435
- [Redirect to another URL](#redirect-to-another-url)
3536
- [Basic response with HTTP Code](#basic-response-with-http-code)
@@ -313,6 +314,20 @@ void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_
313314
}
314315
}
315316
```
317+
If needed, the `_tempObject` field on the request can be used to store a pointer to temporary data (e.g. from the body) associated with the request. If assigned, the pointer will automatically be freed along with the request.
318+
319+
### JSON body handling with ArduinoJson
320+
Endpoints which consume JSON can use a special handler to get ready to use JSON data in the request callback:
321+
```cpp
322+
#include "AsyncJson.h"
323+
#include "ArduinoJson.h"
324+
325+
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint", [](AsyncWebServerRequest *request, JsonVariant &json) {
326+
JsonObject& jsonObj = json.as<JsonObject>();
327+
// ...
328+
});
329+
server.addHandler(handler);
330+
```
316331

317332
## Responses
318333
### Redirect to another URL

src/AsyncJson.h

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// ESPasyncJson.h
1+
// AsyncJson.h
22
/*
3-
Async Response to use with arduinoJson and asyncwebserver
3+
Async Response to use with ArduinoJson and AsyncWebServer
44
Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
55
6-
example of callback in use
6+
Example of callback in use
77
88
server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
99
@@ -17,11 +17,27 @@
1717
request->send(response);
1818
});
1919
20+
--------------------
21+
22+
Async Request to use with ArduinoJson and AsyncWebServer
23+
Written by Arsène von Wyss (avonwyss)
24+
25+
Example
26+
27+
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint");
28+
handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
29+
JsonObject& jsonObj = json.as<JsonObject>();
30+
// ...
31+
});
32+
server.addHandler(handler);
33+
2034
*/
2135
#ifndef ASYNC_JSON_H_
2236
#define ASYNC_JSON_H_
2337
#include <ArduinoJson.h>
2438

39+
const char* JSON_MIMETYPE = "application/json";
40+
2541
/*
2642
* Json Response
2743
* */
@@ -57,7 +73,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
5773
public:
5874
AsyncJsonResponse(bool isArray=false): _isValid{false} {
5975
_code = 200;
60-
_contentType = "application/json";
76+
_contentType = JSON_MIMETYPE;
6177
if(isArray)
6278
_root = _jsonBuffer.createArray();
6379
else
@@ -80,4 +96,68 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
8096
return len;
8197
}
8298
};
99+
100+
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> ArJsonRequestHandlerFunction;
101+
102+
class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
103+
private:
104+
protected:
105+
const String _uri;
106+
WebRequestMethodComposite _method;
107+
ArJsonRequestHandlerFunction _onRequest;
108+
int _contentLength;
109+
int _maxContentLength;
110+
public:
111+
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
112+
void setMethod(WebRequestMethodComposite method){ _method = method; }
113+
void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
114+
void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
115+
116+
virtual bool canHandle(AsyncWebServerRequest *request) override final{
117+
if(!_onRequest)
118+
return false;
119+
120+
if(!(_method & request->method()))
121+
return false;
122+
123+
if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
124+
return false;
125+
126+
if (!request->contentType().equalsIgnoreCase(JSON_MIMETYPE))
127+
return false;
128+
129+
request->addInterestingHeader("ANY");
130+
return true;
131+
}
132+
133+
virtual void handleRequest(AsyncWebServerRequest *request) override final {
134+
if(_onRequest) {
135+
if (request->_tempObject != NULL) {
136+
DynamicJsonBuffer jsonBuffer;
137+
JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject));
138+
if (json.success()) {
139+
_onRequest(request, json);
140+
return;
141+
}
142+
}
143+
request->send(_contentLength > _maxContentLength ? 413 : 400);
144+
} else {
145+
request->send(500);
146+
}
147+
}
148+
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
149+
}
150+
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
151+
if (_onRequest) {
152+
_contentLength = total;
153+
if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) {
154+
request->_tempObject = malloc(total);
155+
}
156+
if (request->_tempObject != NULL) {
157+
memcpy((uint8_t*)(request->_tempObject) + index, data, len);
158+
}
159+
}
160+
}
161+
virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
162+
};
83163
#endif

0 commit comments

Comments
 (0)