Tip: Native case-sensitive Dictionary

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.


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:

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)
End Sub

Sub 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

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:


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( "{}" ) 

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

A JSONItem should be Case Sensitive by now since the JSON spec says so.
Perhaps it can be converted back to a dictionary ?

Notes (from the docs):

Names must be Strings, must be unique within an object and are case-sensitive.

Inspired by @Kem_Tekinay, I have written my own API 2.0 dictionary replacement called BetterDictionary that can be case sensitive or case insensitive (set at instantiation). You can find it within my (new) Xojo-Collections repo.

It has the added advantage that it allows you to mix and match String and Text keys whilst considering them equivalent. I needed this as my current project uses Text throughout and I kept getting caught out by the fact that there is no way in the IDE to write a Text literal. It essentially works around this “bug”:

Var t As Text = "key1"
Var d As New Dictionary("key1" : Nil)

If d.HasKey(t) Then
  Break // Never gets here but the code reads like it should.
End If