Sign in Join

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

Mailing lists / fpc-pascal / 2022-10

Request to make TJSONStreamer.StreamProperty virtual

4 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

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

Hairy Pixels

For the JSON RPC library I wanted to supported dynamic arrays but in order to do this I needed to duplicate TJSONStreamer's ObjectToJSON and StreamProperty in order to bypass some exceptions. If StreamProperty was virtual I could simply override that and stream the dynamic arrays before calling inherited.

What do you think about that?

Regards,
Ryan Joseph

Michael Van Canneyt
to Hairy Pixels
Hairy Pixels wrote
For the JSON RPC library I wanted to supported dynamic arrays but in order to do this I needed to duplicate TJSONStreamer's ObjectToJSON and StreamProperty in order to bypass some exceptions. If StreamProperty was virtual I could simply override that and stream the dynamic arrays before calling inherited. What do you think about that?

It would be a much better idea to implement the streaming of dynamic arrays directly. Then the exceptions are maybe not necessary in the first place...

Michael.

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 14 lines
On Mon, 17 Oct 2022, Hairy Pixels via fpc-pascal wrote: > For the JSON RPC library I wanted to supported dynamic arrays but in order > to do this I needed to duplicate TJSONStreamer's ObjectToJSON and > StreamProperty in order to bypass some exceptions. If StreamProperty was > virtual I could simply override that and stream the dynamic arrays before > calling inherited. > > What do you think about that? It would be a much better idea to implement the streaming of dynamic arrays directly. Then the exceptions are maybe not necessary in the first place...

Small follow-up:

If you want to extend it, you can find the necessary code in the restbase unit. It already implements the necessary code to (de)stream arrays, plus some other enhancements as well. It's on my TODO list to merge the implementations taking TJSONStreamer as a base, but if you are busy with this maybe you can provide a patch...

Michael.

Hairy Pixels
to Michael Van Canneyt
Show quoted text 8 lines
On Oct 17, 2022, at 2:48 PM, Michael Van Canneyt via fpc-pascal wrote: Small follow-up: If you want to extend it, you can find the necessary code in the restbase unit. It already implements the necessary code to (de)stream arrays, plus some other enhancements as well. It's on my TODO list to merge the implementations taking TJSONStreamer as a base, but if you are busy with this maybe you can provide a patch...

I probably don’t know enough about the library to do this well or quickly enough. This is what I hacked together but it only works on the 2 array types I need and I may not have done this correctly even.

function TLSPStreamer.StreamProperty(Const AObject: TObject; PropertyInfo: PPropInfo): TJSONData;
type
  TVariantArray = array of Variant;
  TObjectArray = array of TObject;
var
  PropArray: TJSONArray;
  ElementType: PTypeInfo;
  VariantArray: TVariantArray;
  ObjectArray: TObjectArray;
  i: integer;
begin
  Result := nil;
  if PropertyInfo^.PropType^.Kind = tkDynArray then
    begin
      // Class kinds are in ElType2 (not sure why)
      ElementType := GetTypeData(PropertyInfo^.PropType)^.ElType;
      if ElementType = nil then
        ElementType := GetTypeData(PropertyInfo^.PropType)^.ElType2;
      PropArray := TJSONArray.Create;
      case ElementType^.Kind of
        tkVariant:
          begin
            VariantArray := TVariantArray(GetDynArrayProp(AObject, PropertyInfo));
            for i := 0 to High(VariantArray) do
              PropArray.Add(StreamVariant(VariantArray[i]));
            Result := PropArray;
          end;
        tkClass:
          begin
            ObjectArray := TObjectArray(GetDynArrayProp(AObject, PropertyInfo));
            for i := 0 to High(ObjectArray) do
              PropArray.Add(StreamClassProperty(ObjectArray[i]));
            result := PropArray;
          end;
        otherwise
          raise EUnknownErrorCode.Create('Dynamic array element type "'+Integer(ElementType^.Kind).ToString+'" is not supported for responses.');
      end;
    end
  else
    Result := inherited StreamProperty(AObject, PropertyInfo);
end;

Regards,
Ryan Joseph