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.