Page 1 of 1

Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 9:42 pm
by Quin
I have this code:

Code: Select all

EnableExplicit

Structure Packet
	Type.i
EndStructure

Structure ConnectionPacket Extends Packet
	Who.s
EndStructure

Procedure$ MakePacketJSON(*Packet.Packet)
	Protected Res$
	If CreateJSON(0)
		InsertJSONStructure(JSONValue(0), *Packet, Packet)
		Res$ = ComposeJSON(0)
		FreeJSON(0)
	EndIf
	ProcedureReturn Res$
EndProcedure

Define Base.Packet
Base\Type = 1
Debug MakePacketJSON(@Base)
Define Connection.ConnectionPacket
Connection\Type = 2
Connection\Who = "Me"
Debug MakePacketJSON(@Connection)
It works, but the fields that are exclusive to the extended structure type don't get serialized. I want to have a generic function I can just throw and basic Packet type at and get a JSON-formatted version of it, including all its child fields. I'm writing an app that's going to need many different types of packets and this is what came to mind right away, but it doesn't work. Does anyone here have advice on how to make this work, or better ways to accomplish the same goal?
Thanks,
Quin,.

Re: Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 10:54 pm
by Little John
Hi Quin,

I don't think that doing it exactly the way you want is currently possible with PureBasic. Maybe the easiest way is to implement MakePacketJSON() as Macro rather than as procedure.

Code: Select all

EnableExplicit

Structure Packet
	Type.i
EndStructure

Structure ConnectionPacket Extends Packet
	Who.s
EndStructure

Macro MakePacketJSON (_buffer_, _structure_)
	If CreateJSON(0)
		InsertJSONStructure(JSONValue(0), _buffer_, _structure_)
		Res$ = ComposeJSON(0)
		FreeJSON(0)
	EndIf
EndMacro


Define Base.Packet, Connection.ConnectionPacket, Res$

Base\Type = 1
MakePacketJSON(@Base, Packet)
Debug Res$

Connection\Type = 2
Connection\Who = "Me"
MakePacketJSON(@Connection, ConnectionPacket)
Debug Res$

Re: Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 10:57 pm
by Quin
LittleJohn,
This is perfect! Thank you! I've used macros for tons of stuff like this before, no idea why it didn't come to me here.

Re: Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 10:59 pm
by Little John
I know that effect very well: Sometimes I cannot see the wood for the trees. ;-)

Re: Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 11:32 pm
by Little John
I just had another idea: Pass a generic pointer and an additional 'type' parameter to the procedure MakePacketJSON(). Unfortunately, we can't pass a structure name as parameter to a procedure.

Code: Select all

EnableExplicit

Structure Packet
   Type.i
EndStructure

Structure ConnectionPacket Extends Packet
   Who.s
EndStructure

Procedure$ MakePacketJSON (*p, type.i)
   Protected Res$
   If CreateJSON(0)
      Select type
         Case 1
            InsertJSONStructure(JSONValue(0), *p, Packet)
         Case 2
            InsertJSONStructure(JSONValue(0), *p, ConnectionPacket)
         Default
            ; Error
      EndSelect      
      Res$ = ComposeJSON(0)
      FreeJSON(0)
   EndIf
   ProcedureReturn Res$
EndProcedure

Define Base.Packet
Base\Type = 1
Debug MakePacketJSON(@Base, 1)
Define Connection.ConnectionPacket
Connection\Type = 2
Connection\Who = "Me"
Debug MakePacketJSON(@Connection, 2)

Re: Using InsertJSONStructure with inherited structures?

Posted: Thu Feb 20, 2025 11:57 pm
by Quin
Very nice! I think I still prefer the macro, but this is a neat approach as well.
I wish we could pass a structure name to a procedure like you can to AllocateStructure, InsertJSONStructure etc. from actual PB code. If we could I would just make the function take a structure name as the second parameter instead of a type, so no select is needed. Maybe something for the wishlist.

Re: Using InsertJSONStructure with inherited structures?

Posted: Fri Feb 21, 2025 1:30 am
by idle
This is a case where jsonRuntimeStructure support would be useful, it's what I'm using for my db engine so it can get and set arbitrary user structures via runtime reflection using a string of the type rather than the compile time structure.
so rather than using a bunch of selects on users types to marshal the structures it can be done at runtime.

https://www.purebasic.fr/english/viewto ... 49#p628049