error: no matching function for call to canConvertFromJson
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:42,
from .../ArduinoJson.h:9,
from MyProject.ino:1:
.../ArduinoJson/Variant/ConverterImpl.hpp: In instantiation of 'static bool ArduinoJson::V701PB2::Converter<T, Enable>::checkJson(ArduinoJson::V701PB2::JsonVariantConst) [with T = Point; Enable = void]':
.../ArduinoJson/Variant/VariantRefBase.hpp:99:35: required from 'typename ArduinoJson::V701PB2::detail::enable_if<(((! ArduinoJson::V701PB2::detail::ConverterNeedsWriteableRef<T>::value) && (! ArduinoJson::V701PB2::detail::is_same<T, char*>::value)) && (! ArduinoJson::V701PB2::detail::is_same<T, char>::value)), bool>::type ArduinoJson::V701PB2::detail::VariantRefBase<TDerived>::is() const [with T = Point; TDerived = ArduinoJson::V701PB2::detail::MemberProxy<ArduinoJson::V701PB2::JsonDocument&, const char*>; typename ArduinoJson::V701PB2::detail::enable_if<(((! ArduinoJson::V701PB2::detail::ConverterNeedsWriteableRef<T>::value) && (! ArduinoJson::V701PB2::detail::is_same<T, char*>::value)) && (! ArduinoJson::V701PB2::detail::is_same<T, char>::value)), bool>::type = bool]'
MyProject.ino:11:28: required from here
.../ArduinoJson/Variant/ConverterImpl.hpp:41:30: error: no matching function for call to 'canConvertFromJson(ArduinoJson::V701PB2::JsonVariantConst&, Point&)'
41 | return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v7/unsupported-is/
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
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 {
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