Jump to content

Recommended Posts

Does Delphi have a function in RTL that will encode the text to a form consistent with the JSON value?

 

For example, from string:

 

"value\with
{strange}chars/"

 

to:

 

"\"value\\with\r\n{strange}chars\/\""

 

It is possible?

Share this post


Link to post
20 minutes ago, Jacek Laskowski said:

So... Delphi in the RTL library can't convert text to JSON... Ok.

Hmm, rather perplexing conclusion. How did you arrive at it? 

Share this post


Link to post

The question was simple:
does RTL have functions to convert a string to JSON?

There are two answers:
1. Yes, it's FunctionX function from ModuleY module
2. No, there is no such function

And I asked because I did not find it, and I do not like to reinvent a wheel.

Share this post


Link to post
1 hour ago, Jacek Laskowski said:

So... Delphi in the RTL library can't convert text to JSON... Ok.

Um, yes it can.  It has a full JSON library built-in.

Share this post


Link to post
9 hours ago, Jacek Laskowski said:

The question was simple:
does RTL have functions to convert a string to JSON?

There are two answers:
1. Yes, it's FunctionX function from ModuleY module
2. No, there is no such function

And I asked because I did not find it, and I do not like to reinvent a wheel.

Why did you decide that 2 is the answer? 

Share this post


Link to post
function JsonEncodeString(const AStr: string): string;
var
  LStr: TJSONString;
begin
  LStr := TJSONString.Create(AStr);
  try
    Result := LStr.ToJSON;
    Result := Result.Substring(1, Result.Length - 2);
  finally
    LStr.Free;
  end;
end;

It expects AStr without double quotes, and returns text without double quotes. You can adjust it to your own needs.

Quote

2. No, there is no such function

There are several options, eg with/without double quotes, encode non-ASCII chars/do not encode, etc. Probably more simple to implement the above according your needs.

Edited by Dmitry Arefiev
  • Like 1

Share this post


Link to post

I wish the various Json classes were better documented.  http://docwiki.embarcadero.com/Libraries/Rio/en/REST.JsonReflect is particularly poorly documented with regards to marshalling, interceptors and converters.

I have long been wondering if the TJson.JsonToObject<T>(aJsonString) can be made to handle mixed type arrays {"list": [5, "text", {"prop": "value"}]} by injecting converters, but it seems impossible - but then again - the above mentioned tools are undocumented.

  • Like 1

Share this post


Link to post
16 minutes ago, Lars Fosdal said:

I wish the various Json classes were better documented.  http://docwiki.embarcadero.com/Libraries/Rio/en/REST.JsonReflect is particularly poorly documented with regards to marshalling, interceptors and converters.

I have long been wondering if the TJson.JsonToObject<T>(aJsonString) can be made to handle mixed type arrays {"list": [5, "text", {"prop": "value"}]} by injecting converters, but it seems impossible - but then again - the above mentioned tools are undocumented.

To remember when things were documented is to be old.

  • Like 1
  • Sad 1

Share this post


Link to post

We have two problems:

1) REST, DBX, System.JSON duplicating JSON serialization classes.

2) Non complete docu for (1) classes.

 

We want to keep only System.JSON with options for backward compatibility with REST, DBX. And only to develop System.JSON. When this will happen, then all demos, tests (internal), docu, must be updated to reflect the current RTL state. Now it is not the time for docu work ...

  • Confused 1

Share this post


Link to post
34 minutes ago, Dmitry Arefiev said:

We have two problems:

1) REST, DBX, System.JSON duplicating JSON serialization classes.

2) Non complete docu for (1) classes.

 

We want to keep only System.JSON with options for backward compatibility with REST, DBX. And only to develop System.JSON. When this will happen, then all demos, tests (internal), docu, must be updated to reflect the current RTL state. Now it is not the time for docu work ...

I don't buy that argument.  People are using the software now.  And software is never finished.  There is always more to be done.  So if you wait until it is done, then you never document it.

 

My personal experience, and very strongly felt, is that writing documentation is a key part of finalising and debugging specification.  So many times have I experienced this.  Only when you write the documentation do you realise some of the issues that users will face.  Deal with them before releasing and you don't have to spend as much time in back compat hell.

 

My view is that writing documentation in a timely fashion actually saves time and resources in the long run.

  • Like 5

Share this post


Link to post
4 hours ago, Dmitry Arefiev said:

We have two problems:

...

Now it is not the time for docu work ...

 

CORRECT.  The "time for docu work" was BEFORE THE FEATURE WAS RELEASED.

 

 

  • Like 3

Share this post


Link to post
10 hours ago, Dmitry Arefiev said:

We have two problems:

1) REST, DBX, System.JSON duplicating JSON serialization classes.

2) Non complete docu for (1) classes.

 

We want to keep only System.JSON with options for backward compatibility with REST, DBX. And only to develop System.JSON. When this will happen, then all demos, tests (internal), docu, must be updated to reflect the current RTL state. Now it is not the time for docu work ...

If you don't document it - how do you expect to maintain backward compatibility?


My code relies on REST.Json 

- ObjectInstance := TJson.JsonToObject<T>(aJsonString) ;

- aJsonString := TJson.ObjectToJsonString(ObjectInstance,  [joIgnoreEmptyStrings, joIgnoreEmptyArrays, joDateIsUTC, joDateFormatISO8601]);

- TJSONInterceptor / JsonReflectAttribute for instructing the converter to drop TDateTime properties that have 0 as value.


What are the equivalents in System.Json ?

 

  • Like 1

Share this post


Link to post

Funny thing is, I recently had to think back at how I started with Delphi. Yes I did a bit of Turbo Pascal before, but I can't clearly remember what exactly it was I needed to get fluent in Delphi. As far as I can vaguely remember, it all did start with the documentation and the 'get stated' tutorial. Even if something like that covers the bases, the next step should be obvious. You should have enough knowledge to start a simple project. I remember my first Delphi project was a good old numbers to roman numerals converter. And I took off from there.

 

(And about the initial discussion, sorry but I can't help it, I want people to know: If you know what you're doing, and really really need only the JSON and nothing extra, I've written my own no frills JSON parser here)

Share this post


Link to post
On 6/13/2019 at 12:16 PM, David Heffernan said:

Python documentation is excellent. Likewise C# documentation. And so on. Delphi is an outlier here. 

I've no doubt Delphi is an outlier. The powers that be clearly failed to recognize that the books in the box represented a significant fraction of the value of the product.

Also, there are numerous products for which "documentation" means simply a reference manual, and though such is essential, manuals discussing usage and library application are also important. Delphi once had an array of volumes, and they made it much easier for newcomers to the language to be productive quickly.

  • Like 1

Share this post


Link to post
Guest
On 6/13/2019 at 10:30 PM, David Heffernan said:

Only when you write the documentation do you realise some of the issues that users will face. 

I feel the same so strongly that i feel the need to quote!! Seriously: I manage projects where i factor this in from start. So i put 20% of the dev-budget chronologically after spending 80% of the documentation-budget. Adds a lot of clout. That is if the client admits to having a documentation budget at all (that is a problem, they go - "when it works, we can write the documentation"). Nah.

Share this post


Link to post
Guest

But even if you have a brilliant documentation to your JSON lib it will not cover 100% of the bases that are belong to us:

 

http://seriot.ch/parsing_json.php

 

[I use the value library of RTC - no RTTI, none of the over-complicated PODO to JSON mess, clean and FAST]. Not affiliated.

Share this post


Link to post

BTW, the test suite in above link is 98% successfully passed by 10.3.1 System.JSON. From 7 failing tests, 3-4 may be considered as a "feature" ...

Share this post


Link to post
On 6/7/2019 at 11:49 AM, Jacek Laskowski said:

Does Delphi have a function in RTL that will encode the text to a form consistent with the JSON value?

 

For example, from string:

 

"value\with
{strange}chars/"

 

to:

 

"\"value\\with\r\n{strange}chars\/\""

 

It is possible?

Although Delphi has a native JSON implementation (System.JSON unit) it is not perfect. It seems to be good in parsing, but assembly needs a bit of help. I use it in most of my latest codes though.

To achieve what you'd like:

procedure TForm1.Button1Click(Sender: TObject);
const
 KEK = '"value\with' + sLineBreak + '{strange}chars/"';
Var
 s: TJSONString;
begin
 s := TJSONString.Create(KEK.Replace('\', '\\').Replace(#9, '\t').Replace(sLineBreak, '\n').Replace(#10, '\n').Replace(#13, '\n'));
 Try
  Edit1.Text := s.ToString;
 Finally
  FreeAndNil(s);
 End;
end;

Without the loads of .Replace statements it tends to generate invalid JSONs. So far this chain always fit my needs.
 

It needs a little bit of time to get used to it, but it's lightweight and fast.

 

Edit: I don't think you actually have to escape forward slashes in JSON string literals, they seem to pass validation without them. I did not read the whitesheet though, so I could be wrong. Just add .Replace('/', '\/') in the chain to do that.

Edited by aehimself

Share this post


Link to post
11 hours ago, aehimself said:

To achieve what you'd like:


procedure TForm1.Button1Click(Sender: TObject);
const
 KEK = '"value\with' + sLineBreak + '{strange}chars/"';
Var
 s: TJSONString;
begin
 s := TJSONString.Create(KEK.Replace('\', '\\').Replace(#9, '\t').Replace(sLineBreak, '\n').Replace(#10, '\n').Replace(#13, '\n'));
 Try
  Edit1.Text := s.ToString;
 Finally
  FreeAndNil(s);
 End;
end;

Without the loads of .Replace statements it tends to generate invalid JSONs. So far this chain always fit my needs.

Have you tried toJSON() instead of toString()?

procedure TForm1.Button1Click(Sender: TObject);
const
  KEK = '"value\with' + sLineBreak + '{strange}chars/"';
Var
  s: TJSONString;
begin
  s := TJSONString.Create(KEK);
  Try
    Edit1.Text := s.ToJSON;
  Finally
    s.Free;
  End;
end;

Also, which version of Delphi are you using? Recent versions have made updates to the JSON framework to make it more compliant with the JSON spec.

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

I am using Delphi 10.2.3 and wow, I wish I knew about this before I started my first project... now I have to go back and correct them all 😄

I can confirm that s.ToJSON is producing the exact same output as it was originally requested:

 

s.ToString with the replacements produces "\"value\\with\n{strange}chars/\""

s.ToJSON produces "\"value\\with\r\n{strange}chars\/\""

 

Lesson learned. Do not try to reinvent the wheel, just realize if I messed up the implementation.

(I wonder why it has a .ToString if it is not producing a correct syntax though...)

Share this post


Link to post
On 9/4/2019 at 11:54 PM, aehimself said:

(I wonder why it has a .ToString if it is not producing a correct syntax though...)

I often wonder that myself.  Apparently saving a JSON entity to a string in memory and not do anything else with it is a different operation then saving it to its actual JSON formatted form for storage/transmission.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×