error: no matching function for call to ‘canConvertFromJson(…)’
(applies to ArduinoJson 6.18+)
How do we get this error?
This error occurs when you try to call JsonVariant::is<T>()
with a type T
that ArduinoJson doesn’t support (neither natively nor through a custom converter).
For example, imagine you have the following structure:
struct Point {
int x, y;
};
Suppose your program contains a line like this:
if (doc["point"].is<Point>())
// ...
The compiler will produce an error along those lines:
In file included from [...]/ArduinoJson.hpp:37:0,
from [...]/ArduinoJson.h:9,
from MyProject.ino:9:
[...]/ArduinoJson/Variant/ConverterImpl.hpp: In instantiation of 'static bool Converter<T, Enable>::checkJson(JsonVariantConst) [with T = Point; Enable = void]':
[...]/ArduinoJson/Variant/VariantRefBase.hpp:126:35: required from 'typename enable_if<(((! ConverterNeedsWriteableRef<T>::value) && (! is_same<T, char*>::value)) && (! is_same<T, char>::value)), bool>::type VariantRefBase<TDerived>::is() const [with T = Point; TDerived = MemberProxy<JsonDocument&, const char*>; typename enable_if<(((! ConverterNeedsWriteableRef<T>::value) && (! is_same<T, char*>::value)) && (! is_same<T, char>::value)), bool>::type = bool]'
MyProject.ino:25:25: required from here
[...]/ArduinoJson/Variant/ConverterImpl.hpp:32:30: error: invalid initialization of reference of type 'const String&' from expression of type 'Point'
return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v6/unsupported-is/
~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
[...]/ArduinoJson/Variant/ConverterImpl.hpp:272:13: note: in passing argument 2 of 'bool canConvertFromJson(JsonVariantConst, const String&)'
inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
^~~~~~~~~~~~~~~~~~
How to fix this error?
To allow JsonVariant::is<T>()
to work with a custom T
, you must define a function canConvertFromJson()
like so:
bool canConvertFromJson(JsonVarianConst src, const Point&) {
return src["x"].is<int>() && src["y"].is<int>();
}
The second parameter of canConvertFromJson()
is required to trigger ADL but must not be used by the function.
How to support non-default-constructible types?
Before calling canConvertFromJson()
, ArduinoJson creates an instance of the target type to pass a reference as a second argument.
This requires that the type is default-constructible; otherwise, ArduinoJson wouldn’t know how to construct the instance.
Therefore, you cannot use canConvertFromJson()
for non-default-constructible types.
Instead, you must use a lower-level hook based on the specialization of Converter<T>
, like so:
namespace ARDUINOJSON_NAMESPACE {
template <>
struct Converter<Point> {
static Point checkJson(JsonVariantConst src) {
return src["x"].is<int>() && src["y"].is<int>();
}
// (you'll most likely defined fromJson() too)
};
}
Of course, Point
is default-constructible, but you get the idea, right?
See also
- ArduinoJson 6.18: custom converters
- “Advanced Techniques” chapter in Mastering ArduinoJson