Search code examples
jsondelphimarshalling

Delphi to change JSONMarshalledAttribute in runtime


I have a class in Delphi which I export in jsonmarshalled file.

I am skipping some Fields using the JSONMarshalledAttribute, which resides in the unit: REST.JSON.Types. More literature here

[JSONMarshalledAttribute(False)]                                                                                                                                        
Field1: double;                                                                                                                                                         
[JSONMarshalledAttribute(False)]                                                                                                                                        
Field2: double;                                                                                                                                                         

So far this works great.

My question is: Can I change the JSONMarshalledAttribute to True during runtime?

EDIT 1:

As requested here is the code:

Suppose we have a Form2:TForm and within the form as follows...:

Interface(I am skipping the attributes of the form....)

type                                                                                                                                                                    
  TmyClass = class(Tobject)                                                                                                                                             
  private                                                                                                                                                               
    [JSONMarshalledAttribute(false)]                                                                                                                                    
    FName: string;                                                                                                                                                      
    FVal1: double;                                                                                                                                                      
  public                                                                                                                                                                
    property Name: string read FName write FName;                                                                                                                       
    property Val1: double read FVal1 write FVal1;                                                                                                                       
  end;                                                                                                                                                                  

and then in the implementation:

  procedure TForm2.Button2Click(Sender: Tobject);                                                                                                                       
  var                                                                                                                                                                   
    LArray: TJSONArray;                                                                                                                                                 
  begin                                                                                                                                                                 
    MyClass := TmyClass.Create;                                                                                                                                         
    MyClass.name := 'myNAme';                                                                                                                                           

    LArray := myMarshaler(MyClass, 'FName', True);                                                                                                                      
 end;                                                                                                                                                                   

and the actual function that returns a TJSONArray:

  function TForm2.myMarshaler(myclass: TmyClass; Field: string; Marshal: Boolean)                                                                                       
    : TJSONArray;                                                                                                                                                       
  var                                                                                                                                                                   
    Marshaler: TJSONMarshal;                                                                                                                                            
    JSONObject: TJSONObject;                                                                                                                                            
    LArray: TJSONArray;                                                                                                                                                 
  begin                                                                                                                                                                 
    Marshaler := TJSONMarshal.Create(TJSONConverter.Create);                                                                                                            
    try                                                                                                                                                                 
       Marshaler.RegisterJSONMarshalled(myclass, Field,Marshal);                                                                                                        
      // Marshaler.DateFormat := jdfUnix;                                                                                                                               
      JSONObject := Marshaler.Marshal(myclass) as TJSONObject;                                                                                                          
      LArray := TJSONArray.Create;                                                                                                                                      
      LArray.AddElement(JSONObject);                                                                                                                                    
      result := LArray;                                                                                                                                                 
    finally                                                                                                                                                             
      FreeAndNil(Marshaler);                                                                                                                                            
    end;                                                                                                                                                                
  end;                                                                                                                                                                  

That will not work because Marshaler.RegisterJSONMarshalled requires a TClass as an argument type, but I want to input my own custom classes which are derived from TObject.

and this is the error:

[dcc32 Error] Unit2.pas(134): E2250 There is no overloaded version of >'RegisterJSONMarshalled' that can be called with these arguments

How do I fix this?


Solution

  • You can not change the attribute, but you can overwrite it.

    According to the documentation, it should work with:

    Marshaler.RegisterJSONMarshalled(TYourClass, 'Field1', true);
    

    Therefore, you can not use the class function TJson.ObjectToJsonObject(...), - you'll have to create the marshaller (from the unit REST.JsonReflect) yourself. Example:

    var
      Marshaler: TJSONMarshal;
      JSONObject: TJSOnObject;
    begin
      Marshaler := TJSONMarshal.Create(TJSONConverter.Create);
        try
          Marshaler.RegisterJSONMarshalled(TYourClass, 'Field1');
          Marshaler.DateFormat :=jdfUnix;
          JSONObject := Marshaler.Marshal(AObject) as TJSOnObject;    
          Result := JSONObject;
        finally
          FreeAndNil(Marshaler);
        end;
      end;
    

    To remove the overwritten value you can call UnregisterJSONMarshalled.

    Update to clarify how to this method is called:

    The declared method signature is:

    RegisterJSONMarshalled(clazz: TClass; Field: string; Marshal: Boolean);
    

    So there are three parameters to pass in:

    Marshaler.RegisterJSONMarshalled(myclass.ClassType, Field, Marshal); 
    

    or even more simpler:

    Marshaler.RegisterJSONMarshalled(TMyClass, Field, Marshal); 
    

    You have to pass in the class type of your class.