Issue with ‘.’ instead of ‘..’ when using Exist property on JSON data

Issue with ‘.’ instead of ‘..’ when using Exist property on JSON data

Today, we will discuss an issue that arises from using a single ‘.’ instead of ‘..’ to reference properties of elements in JSON data. This problem surfaced while transitioning to the new prefix syntax coding style. It becomes apparent when checking whether a JSON variable exists in the data returned from an API call. The single ‘.Exist’ syntax can lead to incorrect results, as the code interprets it as referencing a non-existent variable, returning a value of 0, or False. This can have significant unintended consequences in real-world applications.

Prefix Syntax Background

I have been slowly converting my code over to the new prefix syntax. Along with that move, I have also been adjusting my coding style to use a single ‘.’ instead of ‘..’ when referencing properties of elements. We will get into the details of the ‘.’ vs ‘..’ syntax in a bit but first a bit of background on the Prefix Syntax. You can see a good example of the prefix syntax support on this help page https://doc.windev.com/en-US/?1000024323. All of the array functions now have a prefix syntax version. So instead of writing something like this:

I have been gradually transitioning my coding style to the new prefix syntax. As part of this shift, I’ve started using a single ‘.’ instead of ‘..’ to reference properties of elements. We’ll delve into the details of ‘.’ versus ‘..’ syntax shortly, but first, let’s cover some background on the Prefix Syntax. You can find a good example on the help page at https://doc.windev.com/en-US/?1000024323. All array functions now have a prefix syntax version, so you no longer need to write code like this:

myArray is an array of strings
myArray2 is an array of strings

ArrayAdd(myArray,"a")
ArrayAdd(myArray,"a")

ArrayCopy(myArray,myArray2)

ArrayInsert(myArray2,2,"c")

ArrayDelete(myArray2,2)

x is int = ArrayCount(myArray2)

Now we can write that code using the prefix syntax like so:

myArray is an array of strings
myArray2 is an array of strings

myArray.Add("a")
myArray.Add("a")

myArray.Copy(myArray2)

myArray2.Insert(2,"c")

myArray2.Delete(2)

x is int = myArray2.Count()

PCSOFT has been improving support for the prefix syntax for the last few releases. I suspect this is to make WL feel more comfortable to developers in other languages that use a similar prefix syntax. I will admit that the code is a bit more readable, as it is very evident what variables are being affected at a glance, which is why I am slowly adjusting my coding style. I want to be one of the cool kids 😎

Single ‘.’ instead of ‘..’ for referencing Properties

So none of that information directly relates to this article, but at this point, I am sure most of you expected Uncle Pete to ramble on a bit 🙂. Another change that PCSOFT has made is allowing us to reference properties of elements with a single ‘.’ instead of ‘..’ I suspect this again relates to making the code feel more familiar to developers from other languages.

Anytime we wanted to reference a property of an element we had to use the .. syntax. For example, to change the caption of a control the code would be

tblTable..Caption = "My Caption"

Now it is

tblTable.Caption = "My Caption"

I know it’s not a huge thing, but that might total a few thousand extra keystrokes a year 🙂

JSON and Exists Property

Nowadays, most of our work with Web services/API involves RESTful services and JSON data. JSON offers more flexibility than XML, particularly regarding the order of variables and their inclusion in the results.

An example of this is error handling. Many of the APIs I work with will return an Error object in the data when there’s an error. However, they don’t include the object if there’s no error. Here is a response with an error

myJSONWithError is JSON = [
	{
	"CustomerID":1,
	"CompanyName":"Beko",
	"Address":"8574 Hickory Lane",
	"City":"Portland",
	"State":"KY",
	"ZipCode":"93887",
	"EmailAddress":"",
	"StripeCustomerID":"cus_GiX5xGdrUlPdph",
	"error": {
	"code": 123,
	"message": "An error occurred!"
	}
	}
]

And the same response without an error

myJSONWithoutError is JSON = [
	{
	"CustomerID":1,
	"CompanyName":"Beko",
	"Address":"8574 Hickory Lane",
	"City":"Portland",
	"State":"KY",
	"ZipCode":"93887",
	"EmailAddress":"",
	"StripeCustomerID":"cus_GiX5xGdrUlPdph",
	}
]

Due to the dynamic nature of JSON data, I can perform tasks that might not be possible with less flexible data types. Even if I reference the error object when it doesn’t exist, I will still get a value. For example, if I add a couple of trace statements like so:

Trace("With Error = " + myJSONWithError.error.message)
Trace("Without Error = " + myJSONWithoutError.error.message)

I get the following response

	With Error = An error occurred!
	Without Error = 0

Receiving a 0 as a value for a non-existent variable in the data could certainly cause unintended consequences. We cannot code to test for 0 and assume the variable doesn’t exist. This is because we wouldn’t be able to distinguish whether the API genuinely returned 0 or didn’t return the variable at all.

Fortunately, PCSOFT has provided us with a property to test if a variable exists. Here is some sample code to demonstrate its use.

IF myJSONWithError.error..Exist
	Trace("With Error has error object")
ELSE
	Trace("With Error does not have error object")
END	

IF myJSONWithoutError.error..Exist
	Trace("Without Error has error object")
ELSE
	Trace("Without Error does not have error object")
END

And get the following response

	With Error has error object
	Without Error does not have error object

But notice I used the double ‘..’ syntax to use that property. Remember, I have been recently changing my code style to not use the double ‘..’ But guess what happens, in this example if I change the code to the single ‘.’ syntax?

IF myJSONWithError.error.Exist
	Trace("With Error has error object")
ELSE
	Trace("With Error does not have error object")
END	

IF myJSONWithoutError.error.Exist
	Trace("Without Error has error object")
ELSE
	Trace("Without Error does not have error object")
END

Now the response I get is

	With Error does not have error object
	Without Error does not have error object

Ruh-roh, Shaggy! The logic now indicates that the JSON variable containing the error object doesn’t actually have an error. Why is this? It’s because, with the single ‘.’ syntax in this context, WL can’t determine if I’m attempting to use the Exist Property or reference a JSON variable named myJSONWithError.error.Exist. It incorrectly assumes that I’m trying to reference the variable. As we’ve already seen, if that variable doesn’t exist in the JSON data, the result we get is 0, which translates to False. As a result, our code mistakenly believes there isn’t an error 😪.

When examining a screenshot of the code, it’s evident that WL was subtly hinting at an issue. Note that in the double ‘..’ versions, ‘Exist’ is black, indicating it’s a property, while in the single ‘.’ version, it’s the same green color as the rest of the variable.

I would love to say this was just a hypothetical scenario, but it comes from a real-world example. In that project, testing for the existence of a JSON variable in an API call’s return using the single ‘.’ syntax had severe unintended consequences. The time spent finding and fixing the issue far outweighed any time saved by not typing an extra dot 😪.

Leave a comment