I'm using an ESP8266, ArduinoJson v6.21.5. PlatformIO, and Vscode.

The config file is saved and read correctly to the ESP8266's flash:

    "gen_pubTopic": [
    "subTopic": [
    "pubTopic": [

In case the config file is missing, t[], t2[], and t3[] are hard-coded to avoid boot failure.

There are 3 for loops to read topics (from the config file or from hard-coded).

The unexplained part is:

  1. The config file is saved and read as expected, and the code runs without any failure.

  2. when the for loop contains DOC["gen_pubTopic"].size() topics are read as expected, but when it is defined as DOC["gen_pubTopic"].size() |3 it crashes.

  3. x, x2, and x3 are defined before each for loop. Again, once as defined in 2), still no change.

  4. At some part it happened at the 3rd for loop, and sometimes at the 2nd for loop.

  5. Printing xi values shows the expected values.

  6. To make it clear - without using "fallback annotation" |2 the code runs without crashing.

  7. In all stages above - the fallback stage is not tested (meaning- config file is saved and read), and crashes happens when "fallback annotation" is added.

Appreciate any lead why.

void start_iot2(JsonDocument &DOC)
  /* Default values */
  const char *t[] = {"DvirHome/Messages", "DvirHome/log", "DvirHome/debug"};
  const char *t2[] = {"DvirHome/Device", "DvirHome/All"};
  const char *t3[] = {"DvirHome/Device/Avail", "DvirHome/Device/State"};
  uint8_t x = DOC["gen_pubTopic"].size() | 3;
  for (uint8_t i = 0; i < x; i++)
    /* Some Code */
    /* debug code */

  uint8_t x2 = DOC["subTopic"].size() | 2;    
  for (uint8_t i = 0; i < x2; i++)
    /* Some Code */
    /* debug code */
  uint8_t x3 = DOC["pubTopic"].size() | 2;
  for (uint8_t i = 0; i < x3; i++)
    /* Some Code */ 
    /* debug code */

Edit_1 Added /*debug Code */ to for loops. At some point, the Serial Monitor showed:


while the size of the SubTopic array is 4 and |2 as default.

  • 1
    I don't know what you expected | 3 to do.
    – timemage
    Commented Jan 23 at 4:46
  • |3 is set as a value in case config file does not exist
    – guyd
    Commented Jan 23 at 5:38
  • I'm afraid that you don't know what | value actually means. Please edit your question and describe what you think it does in detail. Commented Jan 23 at 7:09
  • |3 is set as a value in case config file does not exist - that isn't what it is doing.
    – Nick Gammon
    Commented Jan 23 at 8:22

1 Answer 1


The "fallback notation" you're referring to is JsonVariant::operator| and only works for JsonVariant.

In your program, you apply | to an unsigned long, so the built-in bitwise "or" operator applies. It performs a bit-by-bit "or" operation (for example 2 | 4 is 6).

In other words, doc["key"] | 4 behaves as you describe, but not doc.size() | 4.

Unlike many other languages, you cannot use logical "or" (||) either because it returns a boolean. So, if you want to make minimal changes to your code, you'll have to do something like this:

uint8_t x = DOC["gen_pubTopic"].size();
if (!x) x = 3;
  • I prefer explicit conditions instead of hidden C features: if (x == 0) // ... ;-) It does not irritate the casual reader of the source and shows the intention much better. Commented Jan 23 at 9:12
  • @Benoit - thank you for a concise answer
    – guyd
    Commented Jan 23 at 9:47
  • I wish to make sure that using iot.add_pubTopic(DOC["pubTopic"][i] | t3[i]); is correct (using t3[i] as "fallback")
    – guyd
    Commented Jan 23 at 9:59
  • Nope, I think not. It looks as if the argument to add_pubTopic is still a unsigned long, for which | means 'bitwise or'. This probably should not even compile, because t3[i] is a string.
    – John
    Commented Jan 23 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.