-
Notifications
You must be signed in to change notification settings - Fork 28
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
Fix: OnDeserialized in superclass is not called #15
Fix: OnDeserialized in superclass is not called #15
Conversation
Previous implementation doesn't call superclass's `OnDeserialized` methods. So I fixed `OnDeserialized` logic. ```typescript ctorsWithOnDeserializedHook = new Array<any>(); var ctor: any = type; while(ctor && typeof (<any>ctor).OnDeserialized === "function") { ctorsWithOnDeserializedHook.push(ctor); if (ctor.prototype && ctor.prototype.__proto__ && ctor.prototype.__proto__.constructor) { /** iff ctor has super class */ ctor = ctor.prototype.__proto__.constructor; } } for (var ctorIndex = 0; ctorIndex < ctorsWithOnDeserializedHook.length; ctorIndex++) { ctorsWithOnDeserializedHook[ctorIndex].OnDeserialized(instance, json); } ``` Previous implementations looks like, ```typescript if (type && typeof (<any>type).OnDeserialized === "function") { (<any>type).OnDeserialized(instance, json); } ```
I enhanced
So we need to track the existence of super classes instead of tracking the existence of |
I definitely agree that the OnDeserialized logic should be extracted into a single function, however I'm unsure that traversing the parent constructor chain and calling As it stands we aren't automatically inheriting parent class serialization because its perfectly possible that a user application would have a single model that wants to serialize / deserialize a child class in a different way than its parent. Since we don't auto-inherit parent serialization, I don't think it makes sense to auto-inherit the deserialization hooks either. That said, I don't have any issues with adding another attribute If we did add that serialization hook inheritance attribute (or argument), I think we can do it by traversing a
2.) It is a bit more efficient to traverse a meta data chain than a constructor chain since we know for sure that only classes with serialized attributes (and hence a Another option is to no longer require What do you think about this? Thanks for the PR, I think this is a great discussion to be having and your contribution is great starting point. |
I have understood what you are worrying about. In regards to API Design, we have two options as you mentioned. (Option A): Adding arguments to // this is impossible because decorator doesn't support named parameters as I know
@inheritSerialization(parent = Person, variable = true, hook = false);
// or we can create Objects for options
// but this is somewhat ambiguous, someone might write as @inheritSerialization(Person, InheritHook, InheritVariable)
@inheritSerialization(Person, InheritVariable, InheritHook) (Option B): Implementing new decorators. In this case, we need two decorators
I think this approach is preferable and more explicit than the previous one // or `@inheriSerialization` to specify both hooks and variables (one-liner)
@inheritSerializationHook
@inheritSerializationVariable
class Student extends Person {
@deserialize public school_name: string;
@deserializeAs("class_number") public class: number;
public GPA: number;
public static OnDeserialized(instance: Student, json: any): void {
....
}
} One more. Is it possible to remove the constructor from decorators? It would be more simple API :) According to this blog, it seems that we can get the constructor without passing as an argument. // http://blog.wolksoftware.com/decorators-reflection-javascript-typescript
// target is the constructor
function log(target: Function, key: string, value: any) {
return {
value: function (...args: any[]) {
var a = args.map(a => JSON.stringify(a)).join();
var result = value.value.apply(this, args);
var r = JSON.stringify(result);
console.log(`Call: ${key}(${a}) => ${r}`);
return result;
}
};
} |
Previous implementation doesn't call superclass's
OnDeserialized
. For example,So I fixed
OnDeserialized
logic (and also included test for it).Previous implementations looks like,
If you don't mind I would like to extract the duplicatd
OnDeserialized
hook logic to 1 function. Since they are the same and exists in two functions (deserializedObject
anddeserializedObjectInto
) And then, we could write tests for it instead of writing test fordeserializedObject
anddeserializedObjectInto
.