ArduinoJson JsonVariant

I've been playing with ArduinoJson V7 a bit.
According to the API documentation, a JsonVariant is a reference to the JSON value.
If the value is a char array then using the JsonVariant or a variable to which I assigned the JsonVariant should be the same thing, namely the reference to the value, in this case a char array.
Example: JSON object = {"DEVICE":"BUZZER"}
To clarify the purpose: the JSON object comes from a JSON doc which is received using serial communication with a phone. The user on the phone provides the name of the "DEVICE" and may or may not strictly comply with omission of blanks and character casing.

JsonVariant j_device = jsonObj["DEVICE"].as<JsonVariant>();
if(j_device == "BUZZER")
{
  // do stuff with BUZZER device
}

This works.

JsonVariant j_device = jsonObj["DEVICE"].as<JsonVariant>();
const char * myDeviceString = j_device.as<const char *>();
if((strcmp(myDeviceString ,"BUZZER") == 0)
{
  // do stuff with BUZZER device
}

does the same thing as the direct comparison with j_device , just a bit more code and an extra variable.
Then I figured, let's handle the JsonVariant j_device just like the variable myDeviceString since they are both references to the same char array.
What I usually do is "normalize" the value when it is a string value: convert all chars to upper or lower case, depending on the purpose and remove all leading and trailing blanks.
All of that works when I use the char * myDeviceString , but when I use the JsonVariant, I can convert the chars to upper or lower case without side-effects (the conversion is done 'in place'); however, when I also remove leading/trailing whitespace the string comparison fails using the JsonVariant j_device , while it still succeeds using the char * myDeviceString . When I print the value - either j_device or myDeviceString - I see the same string "BUZZER", all uppercase and no leading/trailing blanks and length of the string is 6 in both cases.
Why is the comparison failing using the JsonVariant after removing the whitespace?
Code that works (if the value does not contain leading or trailing blanks):

  Serial.print("length of j_device = ");
  Serial.println(strlen(j_device));

  //C_StrTrim(j_device); - commented out for testing
  C_StrToUpper(j_device );

  Serial.print("after fix, length j_device = ");
  Serial.println(strlen(j_device));
  Serial.print("j_device  = ");
  Serial.println(j_device.as<const char *>());
  
  if(j_device == "BUZZER")
  {
       // Trim function commented out
       //comparison yields "true"
  }

Note: I had to add ".as<const char *>()" in the Serial.println statement, because the compiler complained about being "ambiguous".

This code doesn't work if the value contains leading or trailing blanks (for the comparison):

  Serial.print("length of j_device = ");
  Serial.println(strlen(j_device ));

  C_StrTrim(j_device);
  C_StrToUpper(j_device );

  Serial.print("after fix, length j_device = ");
  Serial.println(strlen(j_device));
  Serial.print("j_device  = ");
  Serial.println(j_device.as<const char *>());
  
  if(j_device == "BUZZER")
  {
        // TRIM function NOT commented out
	// comparison yields "false" when the original value contains leading/trailing blanks
  }

Test results:

  • "DEVICE":"BUZZER" => comparison yields "true"
  • "DEVICE":"buZZer" => clean-up produces "BUZZER" and comparison yields "true"
  • "DEVICE":" BUZZER " => original = 8 chars (2 spaces at the end), clean-up produces "BUZZER" (6 chars, no blanks) and comparison yields "false". If I do this using the variable "myDeviceString", then the comparison produces "true".

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.