Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructor and undefined parameters #89

Open
SingeImpetus opened this issue Feb 3, 2019 · 3 comments
Open

Constructor and undefined parameters #89

SingeImpetus opened this issue Feb 3, 2019 · 3 comments
Labels

Comments

@SingeImpetus
Copy link

SingeImpetus commented Feb 3, 2019

Hello,

I'm a bit new to TypeScript, so forgive me if I just made some stupid rookie mistake.

But when defining a simple class,
with a serialized/deserialized member and one not s/d, for whom I would derive a value from the s/d member in the constructor,
it appears the constructor get called with undefined value for parameters:

  @jsonObject
export default class Activity   {

    @jsonMember({ constructor: String })
  timeString : string; // will be 'hh:mm'

  hour? : string; // will be the 'hh' from timeString

  test : string = "no init"; // just for test purpose

  constructor( timeString? : string ) {
    this.test = "first init";
    this.timeString = timeString ? timeString : ""; // modify the s/d member
    
    if( timeString ) { // if it's not undefined
      this.hour = timeString.split(':')[0]; // try to set the not s/d member
      this.test = "right init"; // trace it
    }
    else  
      this.test = "wrong init"; // else, trace it too
  }
}

used to serialized the following file:

{
   "timeString":"09:00"
}

this.hour stays undefined and this.test equals "wrong init" => constructor is called, but with an undefined timeString parameter.
The s/d member get its json's value after the call, so not the one set in the constructor, seems already a bit hard.
But am I doing something wrong?
How am I supposed to init my whole object if it's not in its constructor?

I looked in your source files, and found in deserializer.ts a call for the constructor without the deserialized values:

186         targetObject = this._instantiateType(expectedSelfType);

and "then"

504    private _instantiateType(ctor: any)
          {
              return new ctor();
         }

I'm investigating it by myself, since I'm not sure it's the only constructor call,
but was there a reason to not pass the serialized parameters to the constructor during the process?

@JohnWeisz
Copy link
Owner

JohnWeisz commented Feb 3, 2019

Hey @SingeImpetus,
Indeed you are right, the deserialization process of an object is done in 2 steps:

  1. The class is instantiated using a parameterless constructor signature (this is why constructor( timeString: string) is not allowed, note the lack of ? before the type)
  2. Properties are assigned to the class instance

The idea is that the source JSON should represent the public/serializable portion of your class, and not act as a source of data used to build up your objects manually.

If you need to do additional stuff when deserializing, you should be able to use jsonObject on a getter/setter pair instead, although this hasn't been tested in recent versions:

private _timeString: string;

@jsonMember({ constructor: String })
get timeString(): string {
    return this._timeString;
}
set timeString(timeString: string) {
    this._timeString = timeString;
    this.hour = timeString.split(':')[0]; // try to set the not s/d member
    this.test = "right init"; // trace it
}

@SingeImpetus
Copy link
Author

Ok, I see.
I thought optional parameters were mandatory simply because members could be absent from the parsed json.
Made enough sense. But actually it's more profound and rooted in the process, ok.

I'll look for the setter/getter use.
Thanks.

@Neos3452
Copy link
Collaborator

Sorry SingeImpetus for such a delayed response from me, I somehow must have missed you issue. I have added tests for @jsonMember on getters/setters. You could also try with deserializer option on the decorator if you just need the hour part of the time. You can check the usage in the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants