hydrobyte / McJSON

A Delphi / Lazarus / C++Builder simple and small class for fast JSON parsing.
MIT License
60 stars 20 forks source link

HasKey exception #16

Closed totyaxy closed 1 year ago

totyaxy commented 1 year ago

Hi!

If I want to check whether a particular key exists in a json file (eg config file), I can check it with the HasKey function. The only problem is that it gives an exception (object reference is nil), even though the boolean return value would be enough. During development, it is very unfortunate if unnecessary exceptions interrupt the program execution.

Thank you!

  JsonConfig := TMcJsonItem.Create;
  JsonConfig.LoadFromFile(cConfigFile);

  if not(JsonConfig.HasKey(cOptions)) then;
hydrobyte commented 1 year ago

Hi!

You are right. I had a similar problem last week.

I'll fix it.

Thanks.

totyaxy commented 1 year ago

Thank you, seems to me its working now.

But subkey not found with this method (k1, k2)...

N.AsJSON := '{"o": {"k1":"v1", "k2":"v2"}}';
hydrobyte commented 1 year ago

Hi,

How are you finding a subkey in this example?

totyaxy commented 1 year ago
if N.HasKey('k1') then;
if N.HasKey('o.k1') then;
if N.HasKey('o/k1') then;

But I see in the examples this:

N.AsJSON := '{"o": {"k1":"v1", "k2":"v2"}}';
// type and value: from string to integer
for i := 0 to N['o'].Count-1 do  
  N['o'].Items[i].AsInteger := i+1;   

But it's complete readnig, not only HasKey (key exists?).

hydrobyte commented 1 year ago

HasKey doesn't work like Path

totyaxy commented 1 year ago

I understand, it's just that the name is a bit misleading.

totyaxy commented 1 year ago

Hi!

Just a notice.

"HasKey doesn't work like Path" as you wrote, but I can do similar:

  JsonTmp := JsonConfig.Path(cOptions);
  if not (JsonTmp.HasKey(cAutoBackup)) then
    JsonTmp.Add(cAutoBackup).AsBoolean := FAutoBackup;

This gives me an idea (not an issue), I saw something called "AddOrSet" elsewhere, this would simplify the code, since you don't have to deal with whether the key exists or not, if it does, it sets the value for it, if missing, then will create it. Of course, I see that you have 4 types of Add in your library, so it would be a bit fiddly to implement, if you think it's a good idea at all.

hydrobyte commented 1 year ago

Hi!

Property Shorteners have this "AddOrSet" behavior.

Try this:

  JsonTmp := JsonConfig.Path(cOptions);
  JsonTmp.B[cAutoBackup] := FAutoBackup;
totyaxy commented 1 year ago

Hi, thanks for this information, its works! :)

  JsonTmp := JsonConfig.O[cOptions];

  JsonTmp.B[cAutoBackupBefore] := FAutoBackupBefore;
  JsonTmp.B[cAutoBackupAfter] := FAutoBackupAfter;
  JsonTmp.S[cFileExportFormat] := FFileExportFormat.GetName;

(A side note is that it is important to check whether a key exists in the configuration file, since I give it the default value only if it does not exist, otherwise it would overwrite the existing one. But I understand that you wrote a short example showing the capabilities of the shorteners.)

I have already rewritten part of my code, so it is more transparent and more logical at first, thank you!

hydrobyte commented 1 year ago

Hi

I've mentioned Property Shorteners because they are related with your comment:

This gives me an idea (not an issue), I saw something called "AddOrSet" elsewhere, this would simplify the code, since you don't have to deal with whether the key exists or not, if it does, it sets the value for it, if missing, then will create it.

Also:

A side note is that it is important to check whether a key exists in the configuration file, since I give it the default value only if it does not exist

can be done the way you mentioned:

  JsonTmp := JsonConfig.Path(cOptions);
  if not (JsonTmp.HasKey(cAutoBackup)) then
    JsonTmp.Add(cAutoBackup).AsBoolean := FAutoBackup;
totyaxy commented 1 year ago

It's hard to express myself with a translator, but I'm trying, the idea of AddOrSet was completely independent of the examples, it just came to mind, you obviously wrote an example with what I wrote, you couldn't have done better than that! Just for the sake of completeness, I wrote there as a side note in parentheses that this should be handled carefully in the configuration file (I am precise or I try to be).

The point is that you did everything well, thank you, thank you also for the shortener idea! The wiki did not reveal to me that it also fulfills the function of AddOrSet, perhaps it could be written there, I don't think many people read these issues, especially the closed ones.