Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • A ArduinoJson
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 24
    • Issues 24
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Benoît Blanchon
  • ArduinoJson
  • Issues
  • #1051
Closed
Open
Issue created Jul 16, 2019 by Administrator@rootContributor

String comparison fails when key value is assigned with `const char *` but not String

Created by: sticilface

I've written a function to compare Json objects and bail if the key, values are not found or a different in the target. The target can have more keys.

here is the function

bool DeviceHandle::canHandle(JsonObject & event)
{
	DynamicJsonDocument handleDoc(256); 
	DeserializationError error = deserializeMsgPack(handleDoc, _handle);   //serializeMsgPack

	if (!error) {
		if (handleDoc.is<JsonObject>()) {
			Serial.print("Comparing handleDoc: ");
			serializeJson(handleDoc, Serial); 
			Serial.print("\nwith event:          ");
			serializeJson(event, Serial); 
			Serial.println(); 
			for (JsonPair kv : handleDoc.as<JsonObject>()) {
				if (!event.containsKey(kv.key())) { 
					Serial.printf("  no match, doesn't contain key: %s\n", kv.key().c_str()); 
					return false;  //  if it doesn't contain the key  
				} else if (event.containsKey(kv.key()) && kv.value() != event.getMember(kv.key())) {
					String H;
					String E;
					serializeJson(kv.value(), H);
					serializeJson( event.getMember(kv.key()) , E);
					Serial.printf("  no match, %s [%s != %s]\n", kv.key().c_str(), H.c_str(), E.c_str() ); 					
					return false;  // 
				}
			}
			Serial.println("Event Matches ** ");
			return true; //  if is contains all keys ==. 
		}
	} else {
		Serial.printf("canHandle: Deserialisation error: %s\n", error.c_str()); 
	}

	return false; 
}

Now the input to this function is shown below: type is a string assigned to the key touchtype.


template <>
bool PacketToJson<TouchPacket>(const Packet<TouchPacket> & packet, JsonObject & root)
{
	root["type"] = "TouchPacket"; 
	const char * type = nullptr; 
        //String type; 
	switch (packet.data.touchType.c) {
		case Touch_t::BUTTON_SHORT_PRESS : { type = "short" ;   break; }
		case Touch_t::BUTTON_LONG_PRESS  : { type = "long"  ;   break; }
		case Touch_t::BUTTON_HOLD        : { type = "held"  ;   break; }
		case Touch_t::BUTTON_LEDS        : { type = "leds"  ;   break; }
		case Touch_t::READY              : { type = "ready" ;   break; }
		case Touch_t::NONE               : { type = "none"  ;   break; }
	}
	root["touchtype"] = type;
	root["button"] = packet.data.value; 

	return true;
}

I initially used const char * but the debug output is shown below, and the line kv.value() != event.getMember(kv.key()) was evaluating as false, but you can see from the debug that the values are the same.

Comparing handleDoc: {"source":"TouchTest","touchtype":"short","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":29463,"type":"TouchPacket","touchtype":"short","button":1}
  no match, touchtype ["short" != "short"]  <---   Now this should be true!!!
Comparing handleDoc: {"source":"TouchTest","touchtype":"long","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":29463,"type":"TouchPacket","touchtype":"short","button":1}
  no match, touchtype ["long" != "short"]
Comparing handleDoc: {"source":"TouchTest","touchtype":"held","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":29463,"type":"TouchPacket","touchtype":"short","button":1}
  no match, touchtype ["held" != "short"]

If I then change const char * to String:

[TouchTest] parseEvent: _handles.empty()
Comparing handleDoc: {"source":"TouchTest","touchtype":"short","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":15645,"type":"TouchPacket","touchtype":"short","button":1}
Event Matches ** 
Comparing handleDoc: {"source":"TouchTest","touchtype":"long","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":15645,"type":"TouchPacket","touchtype":"short","button":1}
  no match, touchtype ["long" != "short"]
Comparing handleDoc: {"source":"TouchTest","touchtype":"held","button":1}
with event:          {"source":"TouchTest","pjonID":10,"time":15645,"type":"TouchPacket","touchtype":"short","button":1}
  no match, touchtype ["held" != "short"]

The output works.

So it looks like JsonVariant == operator is not getting it quite right when comparing strings held in the document with those held as a pointer.

Any thoughts?

Assignee
Assign to
Time tracking