Recent

Author Topic: lgenerics TJtdPasCodegen read property null  (Read 1791 times)

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
lgenerics TJtdPasCodegen read property null
« on: December 12, 2023, 03:31:48 pm »
Hi

I tried using TJtdPasCodegen to create a pascal object that imports JSON text.

But I notice that if a JSON property has a value declared as null ...then it is not imported.

This is a problem for me because exporting the data back to JSON loses my null property values.

Note: I'm using this to interface with a third party application that specifies that null values are allowed and are handled differently than the property not be declared at all.

so sending data like this
Code: Text  [Select][+][-]
  1. {  "some_property" : null  }
would give different result than specifying
Code: Text  [Select][+][-]
  1. {    }

Any ideas how to get round this?

Thanks,
Mike

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #1 on: December 12, 2023, 03:49:12 pm »
Could you please clarify which version of the library you are talking about?
A small compilable example demonstrating the unwanted behavior would also be very helpful.

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #2 on: December 12, 2023, 04:32:35 pm »
Hi,

My lgenerics version is 0.5.5.0

I've attached sample program ( proj_nullablle.zip )

Click on the btn_import_export and you should see the json produced is {}

Thanks,
Mike

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #3 on: December 12, 2023, 06:40:51 pm »
Thank you.
Now I see that you are talking about an optional property of a string type.
It seemed to me that the cases when an optional property is Null and its complete absence are almost indistinguishable, isn’t it?

However, if this behavior is unacceptable to you, you can edit the TJObject.DoWriteJson() method:
Code: Pascal  [Select][+][-]
  1. procedure TJObject.DoWriteJson(aWriter: TJsonStrWriter);
  2. begin
  3.   aWriter.BeginObject;
  4.   //if SomeProperty <> nil then begin
  5.   aWriter.AddName('some_property');
  6.   SomeProperty.WriteJson(aWriter);
  7.   //end;
  8.   aWriter.EndObject;
  9. end;
  10.  
« Last Edit: December 12, 2023, 07:00:44 pm by avk »

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #4 on: December 12, 2023, 07:08:11 pm »
Now I see that you are talking about an optional property of a string type.
For the demo I posted, yes it is a string type, but the actual real case for me is both simple and object types.

It seemed to me that the cases when an optional property is Null and its complete absence are almost indistinguishable, isn’t it?
Not in my case, the application I am sending JSON to distinguishes between null and absent. It has a hierarchy of JSON text, a node will "inherit" its parent property, unless it specifies null, in which case it will revert to a platform dependent value completely outside of the JSON hierarchy. I don't have control over the application, it is a Microsoft system. I've confirmed the behaviour by sending null/absent and the system behaves differently.



Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #5 on: December 12, 2023, 07:13:53 pm »
Thanks for the further edit, I must have posted while you were typing.

For modifying the output I think I will have problems because the property will not have been created during the read of the null value.

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #6 on: December 12, 2023, 07:18:20 pm »
I think the part where it checks if the tokenKind = tkNull is my problem, maybe if it could continue but mark itself has having a null value?

Code: Pascal  [Select][+][-]
  1. class function TJtdEntity.ReadJson(aReader: TJsonReader): TJtdEntity;
  2. begin
  3.   if (aReader.ReadState = rsStart) and not aReader.Read then
  4.     ReadError;
  5.   if aReader.TokenKind = tkNull then exit(nil);
  6.   Result := GetJtdClass.Create;
  7.   Result.DoReadJson(aReader);
  8. end;
  9.  

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #7 on: December 12, 2023, 07:28:39 pm »
Quote
  For modifying the output I think I will have problems because the property will not have been created during the read of the null value.
At least your example looks like this after editing.

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #8 on: December 12, 2023, 07:35:52 pm »
But the output will say null, regardless of whether the input was null/absent.

For my case the schema file is over 1300 lines, and the generated pascal is over 8000 lines so I'd rather not have to modify the auto generated code if I can avoid that.

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #9 on: December 12, 2023, 08:10:55 pm »
...
Not in my case, the application I am sending JSON to distinguishes between null and absent.
...
Are you sure you're talking specifically about JSON Type Definition?
It seems to me that such nuances cannot be expressed using JTD, but I would be glad if you could point out the place in the RFC that regulates this.

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #10 on: December 12, 2023, 08:19:58 pm »
It can be tried to change the behavior of the codegenerator, if that suits you.

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #11 on: December 12, 2023, 08:30:48 pm »
It can be tried to change the behavior of the codegenerator, if that suits you.

I think the code generator is ok.. I hacked into lgJtdTypes and can get it to behave they way I wanted, at least for my simple example..

I've attached zip of the modified file (like I say it's just a quick hack)

Note:  I've commented m.c. where I've made changes
« Last Edit: December 12, 2023, 08:37:18 pm by Michael Collier »

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #12 on: December 12, 2023, 08:34:59 pm »
but I would be glad if you could point out the place in the RFC that regulates this.
The link you gave doesn't mention nullable in the contents page, but a page search within the document should bring up plenty of hits

avk

  • Hero Member
  • *****
  • Posts: 771
Re: lgenerics TJtdPasCodegen read property null
« Reply #13 on: December 13, 2023, 11:31:25 am »
Just now tried to modify TJtdEntity a bit to distinguish between null/absent cases for optional properties.
If you're still interested, you can download the current version of the library from github.

Michael Collier

  • Sr. Member
  • ****
  • Posts: 323
Re: lgenerics TJtdPasCodegen read property null
« Reply #14 on: December 13, 2023, 12:06:02 pm »
That's great, thanks for doing that, and so quickly too. I've downloaded just the single file lgjtdtypes.pas - I'm assuming that's the only file I need for this fix (my short sample works ok), until I can install a complete version of lgenerics.

Cheers,
Mike

 

TinyPortal © 2005-2018