error: no matching function for call to ‘Class::Class()’
This error tells you that ArduinoJson tried to instantiate a class but couldn’t find a constructor without arguments.
How did we get there?
This error typically happens when extracting a non-default-constructible type from a JsonDocument
.
For example, if you have a class like this:
class Complex {
double _real, _imag;
public:
// (no default constructor)
explicit Complex(double r, double i) : _real(r), _imag(i) {}
double real() const { return _real; }
double imag() const { return _imag; }
};
If you try to extract a Complex
from a JsonDocument
like this:
Complex sensor = doc["value"];
You will get the following error:
In file included from .../ArduinoJson.hpp:42:0,
from .../ArduinoJson.h:9,
from MyProject.ino:9:
.../ArduinoJson/Variant/ConverterImpl.hpp: In instantiation of 'static T ArduinoJson::V721JB11::Converter<T, Enable>::fromJson(ArduinoJson::V721JB11::JsonVariantConst) [with T = Complex; Enable = void]':
.../ArduinoJson/Variant/VariantRefBaseImpl.hpp:23:32: required from 'T ArduinoJson::V721JB11::detail::VariantRefBase<TDerived>::as() const [with T = Complex; TDerived = ArduinoJson::V721JB11::detail::MemberProxy<ArduinoJson::V721JB11::JsonDocument&, const char*>]'
.../ArduinoJson/Variant/VariantRefBase.hpp:53:17: required from 'ArduinoJson::V721JB11::detail::VariantRefBase<TDerived>::operator T() const [with T = Complex; <template-parameter-2-2> = void; TDerived = ArduinoJson::V721JB11::detail::MemberProxy<ArduinoJson::V721JB11::JsonDocument&, const char*>]'
MyProject.ino:46:31: required from here
.../ArduinoJson/Variant/ConverterImpl.hpp:39:7: error: no matching function for call to 'Complex::Complex()'
T result; // Error here? See https://arduinojson.org/v7/non-default-constructible/
^~~~~~
MyProject.ino:14:12: note: candidate: Complex::Complex(double, double)
explicit Complex(double r, double i) : _real(r), _imag(i) {}
^~~~~~~
MyProject.ino:14:12: note: candidate expects 2 arguments, 0 provided
MyProject.ino:11:7: note: candidate: constexpr Complex::Complex(const Complex&)
class Complex {
^~~~~~~
MyProject.ino:11:7: note: candidate expects 1 argument, 0 provided
MyProject.ino:11:7: note: candidate: constexpr Complex::Complex(Complex&&)
MyProject.ino:11:7: note: candidate expects 1 argument, 0 provided
In file included from .../ArduinoJson.hpp:42:0,
from .../ArduinoJson.h:9,
from MyProject.ino:9:
.../ArduinoJson/Variant/ConverterImpl.hpp:40:20: error: invalid initialization of reference of type 'String&' from expression of type 'Complex'
convertFromJson(src, result); // Error here? See https://arduinojson.org/v7/unsupported-as/
~~~~~~~~~~~~~~~^~~~~~~~~~~~~
.../ArduinoJson/Variant/ConverterImpl.hpp:278:13: note: in passing argument 2 of 'void ArduinoJson::V721JB11::convertFromJson(ArduinoJson::V721JB11::JsonVariantConst, String&)'
inline void convertFromJson(JsonVariantConst src, ::String& dst) {
^~~~~~~~~~~~~~~
How to fix this error?
ArduinoJson supports user-defined types through “custom converters”. You can define converters in two forms:
- Function-based converters, which are the easiest to write but only work for default-constructible types.
- Class-based converters, which are more complex to write but work for any type.
In our example, the type is not default-constructible, so we need to use a class-based converter, such as the following:
namespace ArduinoJson {
template <>
struct Converter<Complex> {
static void toJson(const Complex& src, JsonVariant dst) {
dst["real"] = src.real();
dst["imag"] = src.imag();
}
static Complex fromJson(JsonVariantConst src) {
return Complex(src["real"], src["imag"]);
}
static bool checkJson(JsonVariantConst src) {
return src["real"].is<double>() && src["imag"].is<double>();
}
};
}
The converter class is a specialization of ArduinoJson::Converter<T>
, where T
is the type you want to support.
This specialization must provide the three static methods shown above and be defined in the ArduinoJson
namespace.
See also
- ArduinoJson 6.18: custom converters
- “Advanced Techniques” chapter in Mastering ArduinoJson