hydrobyte / McJSON

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

Unknown escape at pos (escpaing support) #12

Closed totyaxy closed 1 year ago

totyaxy commented 1 year ago

This simple code cause errors (for example in config file):

N.AsJSON := '{"files": {"f1":"c:\a\a.json", "kf":"d:\a\b.json"}}';

It wouldn't be bad if this json library supported json special characters, see:

https://www.tutorialspoint.com/json_simple/json_simple_escape_characters.htm

hydrobyte commented 1 year ago

Hi,

McJSON sopports them. See: ESCAPES

Also, as you have presented, this JSON string isn't valid.

Let Github shows you or try it into JSONlint:

Original:

{"files": {"f1":"c:\a\a.json", "kf":"d:\a\b.json"}}

You need to escape '\' with '\'.

Fixed:

{"files": {"f1":"c:\\a\\a.json", "kf":"d:\\a\\b.json"}}
totyaxy commented 1 year ago

I think the point is that the library should do this automatically. I did it manually already, but this should be done by the library, expanding it when saving to a file, and re-transforming the characters when loading from a file.

For example, I have a json file: { "TestKey": "TestValue\\" }

and then:

procedure TForm1.Button1Click(Sender: TObject); var N: TMcJsonItem; begin N := TMcJsonItem.Create; try N.LoadFromFile('test.json'); Memo1.Lines.Text:=N.AsJSON;
end;

I got the same value:

{"TestKey":"TestValue\\"}

But the correct values are:

{"TestKey":"TestValue\"}

totyaxy commented 1 year ago

Or see this simple code:

procedure TForm1.Button2Click(Sender: TObject); var Json: TMcJsonItem; begin Json := TMcJsonItem.Create(); try Json.Add('key4').AsString := 'value\'; Json.SaveToFile('test2.json'); finally Json.Free; end; end;

I think there should be two \ in the result file, but there aren't.

totyaxy commented 1 year ago

I need edit my posts always, because for the guthub double needed for this : \

hydrobyte commented 1 year ago

Hi,

McJSON parses escapes, as expected. I have a different opinion about "automatically" inserting escapes chars.

Please remember that McJSON also aims to work with C++Builder, what make this kind of "automatic" escaping a little more complicated.

On the other hand, you can do it to your strings before using McJSON. Or you can improve class methods into your fork of McJSON. That's de beauty of open source.

Regards,

totyaxy commented 1 year ago

I understand, thank you, but I think the library would have been more complete if it knew this from the start, but I understand that this is not easy to implement in the various development environments.

hydrobyte commented 1 year ago

Hi,

In general, the way you request something is more important than the content you ask.

I'll think about it.

There was a old issue about this close to the date of the first commit.

Regards,

totyaxy commented 1 year ago

Regarding the way of making the request, I use a translator to keep it understandable, I try to put it simply. Obviously, I would say it differently if I were a native English speaker. I also use another json library, which handles special characters by default, but I would like your excellent library to know it as well (without own code). Thank you!

hydrobyte commented 1 year ago

OK.

hydrobyte commented 1 year ago

Hi, about Escaping a string, please test the latest update.

totyaxy commented 1 year ago

Hi, thanks, but need reverse too (unescape) via load:

procedure TMcJsonItem.LoadFromFile(const aFileName: string; asUTF8: Boolean; const aUnescape: boolean = true);

But this code:

N.AsJSON := '{"o": {"k1":"v1\", "k2":"v2"}}';
Memo1.Lines.Text := N.AsJSON;

result error.

Trunk (main) all test passed!

Thank you!

hydrobyte commented 1 year ago

Hi,

See UnEscapeUnicode().

I'll rename them into next commit.

Best.

totyaxy commented 1 year ago

Hi!

I see these: McJsonEscapeString, McJsonUnEscapeString.

But if I works with json files, I need unescape all string after load (without one by one always). Basically, loading and saving are the most important operations where these escape functions could be performed:

For example:

procedure LoadFromFile(const aFileName: string; asUTF8: Boolean = True; aUnescapeStrings: boolean = true);

and

procedure SaveToFile(const aFileName: string; asHuman: Boolean = True; asUTF8: Boolean = True; aEscapeStrings: boolean = true);

But since it's a json standard, I think it should work that way regardless of any input or parameters.

Thank you!

hydrobyte commented 1 year ago

Hi,

I was looking into Delphi's System.JSON and it has a EscapeString auxiliary function too. In other words, they don't include escapes automatically.

Also, McJSON do read escapes automatically. It is not a JSON property to convert them to the real chars they represent. And I think it is not a good idea to do so. Try JSONLint and you will see that a simple " or \n (a real #13 inside a "value" without escaping) will make your JSON object invalid. You can see this check with the use of the private escapeChar() function.

Although, in the end, you can change your fork as you need.

Thanks for the collaboration.

Regards,

totyaxy commented 1 year ago

Got it, thanks a lot for the info!