Problem

Suppose you have a JsonDocument, named doc, and you want to print the value "myValue".

If you do this:

Serial.println(doc["myValue"]);

you’ll get the following compilation error:

call of overloaded 'println(ArduinoJson6101_00000::enable_if<true, ArduinoJson6101_00000::MemberProxy<ArduinoJson6101_00000::JsonDocument&, const char*> >::type)' is ambiguous

Quite scary, right?

Explanation

It’s not that complicated. The compiler tells us that we passed some obscure type to Serial.println() and that he didn’t know which overload of println() to choose.

What’s an overload, you ask? When the same function has several versions with different parameters, we call each version an “overload.” In our case, Serial.println() has 12 overloads:

size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);

As you can see, there is no overload for JsonVariant, so how can the compiler decide which one to use?

Solution

There are two ways to solve the ambiguity:

  1. You can explicitly cast the JsonVariant to type supported by println()
  2. You can avoid println()

The first solution only works if you know the type of the value. For example, if you know that "myValue" contains an integer, you can write:

Serial.println(doc["myValue"].as<int>());

However, if you don’t know the type, you must use the second solution: replace println() with serializeJson():

serializeJson(doc["myValue"], Serial);

What about Printable?

As you saw above, println() has an overload that takes a Printable, an interface that allows supporting custom types. If JsonVariant implemented Printable, the call to println() would not be ambiguous. So why ArduinoJson doesn’t do that?

Unfortunately, implementing Printable makes the code of the library significantly bigger, and having a small footprint is one of the primary goals of ArduinoJson. Early versions supported Printable, but this feature was removed because it was not worth the extra bytes.