Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2020-08

Null values with JSON RPC

15 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ryan Joseph

I'm trying to get the pascal language server working on Visual Studio Code and during testing I found that sending null values to the server is causing problems. i.e.:

...
"processId": 3997,
"clientInfo": {
"name": "vscode",
"version": "1.47.3"
},
"rootPath": null,
"rootUri": null,
...

This is translated by the RPC layer to a message like:

{"jsonrpc":"2.0","error":{"code":-32603,"message":"Cannot convert data from Null value"},"id":1}

According to the protocol null values are allowed so is there a way I can accept null values gracefully instead of failing with an error? In particular rootPath is trying to be mapped to a string so it could be translated to just '' and that would be better than giving this error that prevents the server from working entirely and causes very confusing errors that are hard to debug.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 22 lines
I'm trying to get the pascal language server working on Visual Studio Code and during testing I found that sending null values to the server is causing problems. i.e.: ... "processId": 3997, "clientInfo": { "name": "vscode", "version": "1.47.3" }, "rootPath": null, "rootUri": null, ... This is translated by the RPC layer to a message like: {"jsonrpc":"2.0","error":{"code":-32603,"message":"Cannot convert data from Null value"},"id":1} According to the protocol null values are allowed so is there a way I can accept null values gracefully instead of failing with an error? In particular rootPath is trying to be mapped to a string so it could be translated to just '' and that would be better than giving this error that prevents the server from working entirely and causes very confusing errors that are hard to debug.

By itself, fpJSON of course allows null values.

What are you using as a serialization technologgy ?

Michael.

Ryan Joseph
to Michael Van Canneyt
Show quoted text 5 lines
On Aug 7, 2020, at 7:58 PM, Michael Van Canneyt wrote: By itself, fpJSON of course allows null values. What are you using as a serialization technologgy ?

I didn't write the serialization layer and this is my first time using the FPCs RTTI system for this purpose. Having said that I think it's coming from TJSONStreamer or TJSONParser as it's trying to decode to a published property like:

    property rootUri: string read fRootUri write fRootUri;

It doesn't seem to know how to translate null to "string", which makes sense I guess but not getting a hard error would be nice simply because it was difficult to understand where it came from and what went wrong. Anybody else trying to integrate into a client will come across this also and be confused.

This is basically like a nullable types problem right? I need to modify the FPC serialization code or use a nullable string type instead of AnsiString.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 15 lines
> On Aug 7, 2020, at 7:58 PM, Michael Van Canneyt wrote: > > By itself, fpJSON of course allows null values. > > What are you using as a serialization technologgy ? I didn't write the serialization layer and this is my first time using the FPCs RTTI system for this purpose. Having said that I think it's coming from TJSONStreamer or TJSONParser as it's trying to decode to a published property like: property rootUri: string read fRootUri write fRootUri; It doesn't seem to know how to translate null to "string", which makes sense I guess but not getting a hard error would be nice simply because it was difficult to understand where it came from and what went wrong. Anybody else trying to integrate into a client will come across this also and be confused. This is basically like a nullable types problem right? I need to modify the FPC serialization code or use a nullable string type instead of AnsiString.

An option to allow nulls to be detected and handles would of course be a nice addition.

For the time being, you can just set jdoIgnorePropertyErrors on the destreamer options.

Michael.

Ryan Joseph
to Michael Van Canneyt
Show quoted text 6 lines
On Aug 7, 2020, at 8:31 PM, Michael Van Canneyt wrote: An option to allow nulls to be detected and handles would of course be a nice addition. For the time being, you can just set jdoIgnorePropertyErrors on the destreamer options.

Quick check right now and setting that option still seems to give the same error. I'll look into it more tomorrow when I have some time. There's seems to be a DoRestoreProperty override which could be interesting but I'm not sure if the error is trigger before here or not.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 13 lines
> On Aug 7, 2020, at 8:31 PM, Michael Van Canneyt wrote: > > An option to allow nulls to be detected and handles would of course be a nice > addition. > > For the time being, you can just set jdoIgnorePropertyErrors on the destreamer options. Quick check right now and setting that option still seems to give the same error. I'll look into it more tomorrow when I have some time. There's seems to be a DoRestoreProperty override which could be interesting but I'm not sure if the error is trigger before here or not.
try
     B:=Not Assigned(FOnRestoreProp);
     If Not B then
       begin
       FOnRestoreProp(Self,AObject,PropInfo,PropData,B);
       If B then
         exit;
       end;
     DoRestoreProperty(AObject,PropInfo,PropData);
   except
     On E : Exception do
       If Assigned(FOnPropError) then
         begin
         B:=False;
         FOnPropError(Self,AObject,PropInfo,PropData,E,B);
         If Not B then
           Raise;
         end
       else if Not (jdoIgnorePropertyErrors in Options) then
         Raise;
   end;

The exception will still be raised, but should be caught.

I added a jdoIgnoreNulls which changes the above to:

   if (PropData.JSONType=jtNull) then
       if Not (jdoIgnoreNulls in Options) then
         DoRestoreProperty(AObject,PropInfo,PropData);

Committed in SVN. I will still add a jsoNullClearsProperty which will clear the property using the 'natural' empty value (0, Nil, '' etc).

Michael.

Ryan Joseph
to Michael Van Canneyt
On Aug 7, 2020, at 9:09 PM, Michael Van Canneyt wrote: try B:=Not Assigned(FOnRestoreProp);

I just rebuilt the compiler (couldn't figure out how to recompile just the fpc-json package) and got the new changes but there seems to be a regression and I'm not getting anything deserialized now. Maybe something else is the culprit but it's totally broken now for some reason. Can you test and confirm this?

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 12 lines
> On Aug 7, 2020, at 9:09 PM, Michael Van Canneyt wrote: > > try > B:=Not Assigned(FOnRestoreProp); I just rebuilt the compiler (couldn't figure out how to recompile just the fpc-json package) and got the new changes but there seems to be a regression and I'm not getting anything deserialized now. Maybe something else is the culprit but it's totally broken now for some reason. Can you test and confirm this?

Confirm there was an error. Fixed, and added testcase.

I also added jdoNullClearsProperty; a null will then clear the property with the 'natural' empty value. It has precedence over jdoIgnoreNulls.

Michael.

Ryan Joseph
to Michael Van Canneyt
Show quoted text 6 lines
On Aug 8, 2020, at 7:37 PM, Michael Van Canneyt wrote: Confirm there was an error. Fixed, and added testcase. I also added jdoNullClearsProperty; a null will then clear the property with the 'natural' empty value. It has precedence over jdoIgnoreNulls.

Thanks again, I couldn't figure out what I did wrong! Btw, can I just rebuild the fpc-json package? I ended up rebuilding everything to get just that one change. The project was started using lazbuild so I'm kind of tied into that build system even though I don't understand how it works very well. Normally I would just add paths to directories and I need but that's not an option with lazbuilds package system.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 11 lines
> On Aug 8, 2020, at 7:37 PM, Michael Van Canneyt wrote: > > Confirm there was an error. Fixed, and added testcase. > > I also added jdoNullClearsProperty; a null will then clear the property with > the 'natural' empty value. It has precedence over jdoIgnoreNulls. Thanks again, I couldn't figure out what I did wrong! Btw, can I just rebuild the fpc-json package?

Sure, I do it all the time.

I ended up rebuilding everything to get just that one change. The project was started using lazbuild so I'm kind of tied into that build system even though I don't understand how it works very well. Normally I would just add paths to directories and I need but that's not an option with lazbuilds package system.

if you have the sources of FPC somewhere, in a terminal, change to directory "packages"

Then do a

make clean
make install PREFIX=/some/dir/on/your/system

That should do the trick. It will simply rebuild & install all packages.

You can do the same in the packages/fcl-json directory, but then some other files that depend on fcl-json will also need rebuilding. So that's only when you know what you're doing...

Michael.

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 7 lines
> On Aug 8, 2020, at 8:24 PM, Michael Van Canneyt wrote: > > make clean make install PREFIX=/some/dir/on/your/system what is the PREFIX part?

I don't know, that depends on your system. It is the path where FPC is installed.

On my linux, this is
/usr/local
on my windows, this is
c:\FPC\trunk\

The install command will then append the necessary directories to this prefix.

Michael.

Ryan Joseph
to Michael Van Canneyt
On Aug 8, 2020, at 8:37 PM, Michael Van Canneyt wrote: I don't know, that depends on your system. It is the path where FPC is installed.

It's the compiler path? This is the same errors I got before which made me rebuild the compiler (macOS btw)

packages$ sudo make clean make install PREFIX=/usr/local/lib/fpc/3.3.1/ppcx64 Password:
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C fpmkunit clean_bootstrap /bin/rm -rf units_bs
./fpmake clean --localunitdir=.. --os=darwin --cpu=x86_64 -o -dx86_64 --compiler=/usr/local/bin/ppcx64 -bu Warning: Removed non empty directory "univint/units/x86_64-darwin/" make: *** No rule to make target `make'. Stop.
packages$

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 7 lines
> On Aug 8, 2020, at 8:37 PM, Michael Van Canneyt wrote: > > I don't know, that depends on your system. It is the path where FPC is installed. It's the compiler path? This is the same errors I got before which made me rebuild the compiler (macOS btw)

No, not the compiler path. The directory below which FPC is installed.

Show quoted text 9 lines
packages$ sudo make clean make install PREFIX=/usr/local/lib/fpc/3.3.1/ppcx64 Password: /Applications/Xcode.app/Contents/Developer/usr/bin/make -C fpmkunit clean_bootstrap /bin/rm -rf units_bs ./fpmake clean --localunitdir=.. --os=darwin --cpu=x86_64 -o -dx86_64 --compiler=/usr/local/bin/ppcx64 -bu Warning: Removed non empty directory "univint/units/x86_64-darwin/" make: *** No rule to make target `make'. Stop. packages$

That's because you specified the "make" target to your make command... :-)

Try this (as separate commands):
sudo make clean
sudo make all
sudo make install PREFIX=/usr/local/

You can try to combine it with

sudo make clean all install PREFIX=/usr/local/

But I never do that.

In general, I never compile as root, so I tend to do:

make clean
make all
sudo make install PREFIX=/usr/local/

But once you started as root, you must at least also run make clean as root, once.

Michael.

Joost van der Sluis
to Michael Van Canneyt: Sure, I do it all the time. if you have the sources of FPC somewhere, in a terminal,…

Op 08-08-2020 om 15:24 schreef Michael Van Canneyt:

Show quoted text 36 lines
On Sat, 8 Aug 2020, Ryan Joseph via fpc-pascal wrote: > >> On Aug 8, 2020, at 7:37 PM, Michael Van Canneyt >> wrote: >> >> Confirm there was an error. Fixed, and added testcase. >> >> I also added jdoNullClearsProperty; a null will then clear the >> property with >> the 'natural' empty value. It has precedence over jdoIgnoreNulls. > > Thanks again, I couldn't figure out what I did wrong! Btw, can I just > rebuild the fpc-json package? Sure, I do it all the time. > I ended up rebuilding everything to get just that one change. The > project was started using lazbuild so I'm kind of tied into that build > system even though I don't understand how it works very well. Normally > I would just add paths to directories and I need but that's not an > option with lazbuilds package system. if you have the sources of FPC somewhere, in a terminal, change to directory "packages" Then do a make clean make install PREFIX=/some/dir/on/your/system That should do the trick. It will simply rebuild & install all packages. You can do the same in the packages/fcl-json directory, but then some other files that depend on fcl-json will also need rebuilding. So that's only when you know what you're doing...

Or when your fpc-setup is alright:

cd packages/fcl-json
fppkg install -o -gl

The "-o -gl" part is to include debug-info. It will also automatically recompile all dependencies. (So no need to know what you are doing - Michael's words)

Regards,

Joost.