error: ambiguous overload for ‘operator=’ (operand types are ‘String’ and …)
(applies to all revisions of ArduinoJson 6)
What’s the problem?
Due to the way JsonVariant
and String
implement implicit type conversion, you can construct a String
from a JsonVariant
, but you cannot assign a JsonVariant
to an existing String
.
For example, in the following snippet, the first line works but the second produces a compilation error:
String name = doc["name"]; // contruction -> works
name = doc["name"]; // assignment -> fails
If you try to compile this snippet, you get the following error:
error: ambiguous overload for 'operator=' (operand types are 'String' and ...)
name = doc["name"];
^
note: candidate: String& String::operator=(const String&)
note: candidate: String& String::operator=(const char*)
note: candidate: String& String::operator=(const __FlashStringHelper*)
note: candidate: String& String::operator=(String&&)
note: candidate: String& String::operator=(StringSumHelper&&)
Indeed, since JsonVariant
supports implicit conversion to both const char*
and String
, the compiler doesn’t know which constructor of String
should be called, so it deems the operator as “ambiguous”.
How to solve it?
Solution 1: cast
We need to help the compiler pick the right constructor of String
.
One way is to cast the JsonVariant
to const char*
, like so:
name = (const char*)doc["name"];
Note that we cannot cast to String
because it’s equivalent to calling the (ambiguous) constructor.
Solution 2: as<T>()
Another way is to use JsonVariant::as<T>()
, which explicitly converts the JsonVariant
to the specified type.
For example, any of these lines would work:
name = doc["name"].as<const char*>();
name = doc["name"].as<String>();
Solution 3: no String
Lastly, like most String
class issues, the best solution is often to replace it with a const char*
or a char[]
.
Indeed, the problem doesn’t exists with const char*
:
const char* name = doc["name"]; // contruction -> works
name = doc["name"]; // assignment -> works as well
Just remember that the variable name points to the value in the JsonDocument
, so it’s not a copy.
Instead, if you need to make a copy you can use a char[]
like so:
char name[32];
strlcpy(name, doc["name"] | "", 32);
When you use strcpy()
or strlcpy()
, always provide a default value (""
, here) because passing NULL
to these functions leads to undefined behavior.