AsyncJson.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // AsyncJson.h
  2. /*
  3. Async Response to use with ArduinoJson and AsyncWebServer
  4. Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
  5. Example of callback in use
  6. server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
  7. AsyncJsonResponse * response = new AsyncJsonResponse();
  8. JsonObject& root = response->getRoot();
  9. root["key1"] = "key number one";
  10. JsonObject& nested = root.createNestedObject("nested");
  11. nested["key1"] = "key number one";
  12. response->setLength();
  13. request->send(response);
  14. });
  15. --------------------
  16. Async Request to use with ArduinoJson and AsyncWebServer
  17. Written by Arsène von Wyss (avonwyss)
  18. Example
  19. AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint");
  20. handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
  21. JsonObject& jsonObj = json.as<JsonObject>();
  22. // ...
  23. });
  24. server.addHandler(handler);
  25. */
  26. #ifndef ASYNC_JSON_H_
  27. #define ASYNC_JSON_H_
  28. #include <ArduinoJson.h>
  29. #include <ESPAsyncWebServer.h>
  30. #include <Print.h>
  31. #if ARDUINOJSON_VERSION_MAJOR == 5
  32. #define ARDUINOJSON_5_COMPATIBILITY
  33. #else
  34. #ifndef DYNAMIC_JSON_DOCUMENT_SIZE
  35. #define DYNAMIC_JSON_DOCUMENT_SIZE 1024
  36. #endif
  37. #endif
  38. constexpr const char* JSON_MIMETYPE = "application/json";
  39. /*
  40. * Json Response
  41. * */
  42. class ChunkPrint : public Print {
  43. private:
  44. uint8_t* _destination;
  45. size_t _to_skip;
  46. size_t _to_write;
  47. size_t _pos;
  48. public:
  49. ChunkPrint(uint8_t* destination, size_t from, size_t len)
  50. : _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
  51. virtual ~ChunkPrint(){}
  52. size_t write(uint8_t c){
  53. if (_to_skip > 0) {
  54. _to_skip--;
  55. return 1;
  56. } else if (_to_write > 0) {
  57. _to_write--;
  58. _destination[_pos++] = c;
  59. return 1;
  60. }
  61. return 0;
  62. }
  63. size_t write(const uint8_t *buffer, size_t size)
  64. {
  65. return this->Print::write(buffer, size);
  66. }
  67. };
  68. class AsyncJsonResponse: public AsyncAbstractResponse {
  69. protected:
  70. #ifdef ARDUINOJSON_5_COMPATIBILITY
  71. DynamicJsonBuffer _jsonBuffer;
  72. #else
  73. DynamicJsonDocument _jsonBuffer;
  74. #endif
  75. JsonVariant _root;
  76. bool _isValid;
  77. public:
  78. #ifdef ARDUINOJSON_5_COMPATIBILITY
  79. AsyncJsonResponse(bool isArray=false): _isValid{false} {
  80. _code = 200;
  81. _contentType = JSON_MIMETYPE;
  82. if(isArray)
  83. _root = _jsonBuffer.createArray();
  84. else
  85. _root = _jsonBuffer.createObject();
  86. }
  87. #else
  88. AsyncJsonResponse(bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
  89. _code = 200;
  90. _contentType = JSON_MIMETYPE;
  91. if(isArray)
  92. _root = _jsonBuffer.createNestedArray();
  93. else
  94. _root = _jsonBuffer.createNestedObject();
  95. }
  96. #endif
  97. ~AsyncJsonResponse() {}
  98. JsonVariant & getRoot() { return _root; }
  99. bool _sourceValid() const { return _isValid; }
  100. size_t setLength() {
  101. #ifdef ARDUINOJSON_5_COMPATIBILITY
  102. _contentLength = _root.measureLength();
  103. #else
  104. _contentLength = measureJson(_root);
  105. #endif
  106. if (_contentLength) { _isValid = true; }
  107. return _contentLength;
  108. }
  109. size_t getSize() { return _jsonBuffer.size(); }
  110. size_t _fillBuffer(uint8_t *data, size_t len){
  111. ChunkPrint dest(data, _sentLength, len);
  112. #ifdef ARDUINOJSON_5_COMPATIBILITY
  113. _root.printTo( dest ) ;
  114. #else
  115. serializeJson(_root, dest);
  116. #endif
  117. return len;
  118. }
  119. };
  120. class PrettyAsyncJsonResponse: public AsyncJsonResponse {
  121. public:
  122. #ifdef ARDUINOJSON_5_COMPATIBILITY
  123. PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {}
  124. #else
  125. PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {}
  126. #endif
  127. size_t setLength () {
  128. #ifdef ARDUINOJSON_5_COMPATIBILITY
  129. _contentLength = _root.measurePrettyLength ();
  130. #else
  131. _contentLength = measureJsonPretty(_root);
  132. #endif
  133. if (_contentLength) {_isValid = true;}
  134. return _contentLength;
  135. }
  136. size_t _fillBuffer (uint8_t *data, size_t len) {
  137. ChunkPrint dest (data, _sentLength, len);
  138. #ifdef ARDUINOJSON_5_COMPATIBILITY
  139. _root.prettyPrintTo (dest);
  140. #else
  141. serializeJsonPretty(_root, dest);
  142. #endif
  143. return len;
  144. }
  145. };
  146. typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> ArJsonRequestHandlerFunction;
  147. class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
  148. private:
  149. protected:
  150. const String _uri;
  151. WebRequestMethodComposite _method;
  152. ArJsonRequestHandlerFunction _onRequest;
  153. size_t _contentLength;
  154. #ifndef ARDUINOJSON_5_COMPATIBILITY
  155. const size_t maxJsonBufferSize;
  156. #endif
  157. size_t _maxContentLength;
  158. public:
  159. #ifdef ARDUINOJSON_5_COMPATIBILITY
  160. AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest)
  161. : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
  162. #else
  163. AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE)
  164. : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
  165. #endif
  166. void setMethod(WebRequestMethodComposite method){ _method = method; }
  167. void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
  168. void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
  169. virtual bool canHandle(AsyncWebServerRequest *request) override final{
  170. if(!_onRequest)
  171. return false;
  172. if(!(_method & request->method()))
  173. return false;
  174. if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
  175. return false;
  176. if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) )
  177. return false;
  178. request->addInterestingHeader("ANY");
  179. return true;
  180. }
  181. virtual void handleRequest(AsyncWebServerRequest *request) override final {
  182. if(_onRequest) {
  183. if (request->_tempObject != NULL) {
  184. #ifdef ARDUINOJSON_5_COMPATIBILITY
  185. DynamicJsonBuffer jsonBuffer;
  186. JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject));
  187. if (json.success()) {
  188. #else
  189. DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
  190. DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
  191. if(!error) {
  192. JsonVariant json = jsonBuffer.as<JsonVariant>();
  193. #endif
  194. _onRequest(request, json);
  195. return;
  196. }
  197. }
  198. request->send(_contentLength > _maxContentLength ? 413 : 400);
  199. } else {
  200. request->send(500);
  201. }
  202. }
  203. virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
  204. }
  205. virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
  206. if (_onRequest) {
  207. _contentLength = total;
  208. if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) {
  209. request->_tempObject = malloc(total);
  210. }
  211. if (request->_tempObject != NULL) {
  212. memcpy((uint8_t*)(request->_tempObject) + index, data, len);
  213. }
  214. }
  215. }
  216. virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
  217. };
  218. #endif