Tip: Native case-sensitive Dictionary

The native Dictionaries, classic and new, will treat Text and String keys without regard to case, but sometimes you need it to be case-sensitive. While the Xojo.Core.Dictionary gives you the tools to roll your own, did you know that Xojo will generate one for your natively?

Just do this:

dim caseSensitiveDict as Xojo.Core.Dictionary = Xojo.Data.ParseJSON( "{}" )

JSON is case-sensitive so the Xojo Dictionary that represents JSON must be too. By parsing an empty JSON object, Xojo will generate a special, case-sensitive, empty Dictionary.

Be careful though. In the debugger, you cannot differentiate this case-sensitive Dictionary from a “normal” one so be sure to keep track yourself and use the case-sensitive version only when and where needed.

If you need to be able to test, create a subclass of the Xojo.Core.Dictionary and implement the CompareKeys event.

1 Like

It’s not exceedingly special. It’s no different than if one were to implement the CompareKeys event and call Text.Compare from it.

OK, it generates a not-so-special, case-sensitive Dictionary. :slight_smile:

But I do wish it would generate a subclass instead so we can tell within the debugger or test for its case-sensitivity in code.

<https://xojo.com/issue/39002>

That’s a nice tip too.

Could you not add a boolean property CaseSensitiveCompare and implement the Text.Compare in a dictionary subclass with

If CaseSensitiveCompare Â…

Yes, but that doesn’t help when parsing JSON.

What a great find Kem!

I’ve created a subclass imaginatively called CaseSensitiveDictionary which acts as a drop-in replacement for the Xojo.Core.Dictionary class with the exception that iterating through it requires a slight change:

dim d as new CaseSensitiveDictionary for each entry as Xojo.Core.DictionaryEntry in d.data ' Do something next entry

Here’s the class:

[code]Methods
Function Clone() As CaseSensitiveDictionary
dim c as new CaseSensitiveDictionary
c.data = data.Clone
return c
End Function

Sub Constructor()
self.data = Xojo.Data.ParseJSON( “{}” )
End Sub

Function Count() As Integer
return data.Count
End Function

Function HasKey(key As Auto) As Boolean
return data.HasKey(key)
End Function

Function Lookup(key As Auto, defaultValue As Auto) As Auto
return data.Lookup(key, defaultValue)
End Function

Sub Remove(key As Auto)
data.Remove(key)
End Sub

Sub RemoveAll()
data.RemoveAll()
End Sub

Function Value(key As Auto) As Auto
return data.Value(key)
End Function

Sub Value(key As Auto, Assigns value As Auto)
data.Value(key) = value
End Sub

Properties
data As Xojo.Core.Dictionary[/code]

It would seem fairly easy to EncodeBase64 the key, so any dictionary becomes case sensitive, not just Xojo.Code.Dictionary, but also classic Dictionary.

A subclass seems easy enough to create, based on that principle.

You can use Hex, not Base64, as the latter is a case-sensitive too.

If the trick in the original post still works I feel like it’d just be easier to do the trick than subclass dictionary!

The trick does still work (thankfully). The advantage of a subclass is that it prevents you from accidentally forgetting to use the hack when you instantiate a new Dictionary.

I’ve been playing around with this today and the trick still works. I wonder if there’s any re-assurance from Xojo that this will always be the case? I tried to subclass Xojo.Core.Dictionary and implement the CompareKeys event handler myself but quite frankly it seems to be a HUGE amount of work to support comparisons between all different key types. I just feel a little nervous deploying this code if Xojo breaks it in the next release…

Other than the Xojo.* stuff being deprecated eventually, I don’t see why this would ever change. The JSON spec calls for case-sensitive keys.

BTW, I implemented a case-sensitive Dictionary subclass here:

http://www.mactechnologies.com/index.php?page=downloads#case_sensitive_dictionary

Good point Kem. I think I will trust it’ll survive. I’m well known for unnecessarily re-inventing the wheel…

UPDATE: With API 2, you can do the same:

var caseSensitiveDict as Dictionary = ParseJSON( "{}" ) 
3 Likes

Regarding your comment about being able to tell if it’s case-sensitive, we can’t actually tell that. You could (for instance) have a delegate which only checked for case-sensitivity on works that start with a-m, but not with ones that start with n-z, and we’d have no way to know that. Nor are keys always strings.

FYI, this no longer works (as of Xojo 2021 r2.1) for Text keys. They are now case-insensitive even with this “hack”.