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".