Since ArduinoJson 5.8, parseArray() and parseObject() accept Arduino’s Stream and std::istream as input:

JsonObject& root = jsonObject.parseObject(myStream);

Parts of the input need to be copied into the JsonBuffer, so you need to increase its capacity accordingly (the Assistant gives the required size).

The parser only copies the relevant part of the input, skipping the spaces and the punctuation. This is way more efficient than copying the whole input in a char[] and then call parseObject().

Example: parse JSON from SPIFFS

// Initialize SPIFFS

// Open the File (which implements Stream)
File file ="config.json", "r");

// Let ArduinoJson read directly from File
DynamicJsonBuffer jb;
JsonObject& config = jb.parseObject(file);

// We don't need the file anymore