-
Notifications
You must be signed in to change notification settings - Fork 34
Type being known at runtime. #25
Comments
We came across this while one of our model class that had few subclasses was being used as a field in another class. While debugging we found out that although the type of field was one of the subclasses, the adapter that was being used to parse the same was of the super class type, hence not able to serialize the fields of subclasses |
I'm not sure I completely understand the situation. Is this the sort of structure you're referring to? class ClassA<T> {
T unknownField;
}
class ClassB extends ClassA<ClassA<String>> {
// some more fields
} We have a similar use case, which isn't experiencing any problems (see https://github.com/vimeo/vimeo-networking-java/blob/v2.0.0/vimeo-networking/src/main/java/com/vimeo/networking/model/Category.java). But our example uses a |
Lets assume we have subclasses of class public class User {
public String name;
}
public class UserWithAddress extends User {
public String address;
}
public class UserWithoutAddress extends User {
public String location;
} Now, in Video class, we have User class as a field public class Video {
public User user;
} Suppose the type of User field is known at runtime ie, it may be UserWithAddress or UserWithoutAddress or can be User simply. If it is of type User, everything will be work fine. But if its one of UserWithAddress or UserWithoutAddress, since stag does not know the actual type, and assumes it to be of type User, it will use the typeadapter of User to serialize it which will result in fields of the actual type not getting serialized. Let me know if this helps |
Okay that's a much simpler scenario than I thought, thanks for the clarification. This is definitely an important use case, i'll think on it. |
Sure. We fixed this using the annotation, looking forward for an alternative solution :) Thank you |
@anthonycr Any updates on this ? Would be great if this gets resolved in the upcoming release. |
Okay, so if we introduce a class Parent {
String name;
}
class Child extends Parent {
String name1;
}
class Other {
Parent parent;
}
// generated
class Other$TypeAdapter {
void write() {
// other stuff
// if (parent field annotated with RuntimeType)
mGson.getAdapter(object.mParentType.getClass()).write();
// else
mStagFactory.getParentType$TypeAdapter(mGson).write();
}
} This doesn't solve the whole problem, because the type isn't known when parsing the json, so then when you parse the correct json it will just lose the field because it will try to parse it as a parent type. Of course, if you don't need to deserialize it once it's been serialized then it will work fine. |
Yes. You're right. I tried the same thing with Gson as well, it does not deserialize it with the correct type. |
Do you think it's worth implementing the serialization half of this anyway? That would at least mirror gson's behavior, but at the same time I feel like it's not worth adding in new stuff for a half solve |
Ideal case would be that people use class Other { This is a better way to represent it anyways where there are no run time checks for the type. I guess a more generic requirement that might exists (for certain other corner/unknown/unhandled/stag-being-buggy scenario) is to allow certain fields of a class to be defaulted to Gson parsing. Since this would be an exception we can call this annotation as @UseGson which is a field level annotation only. Thoughts? |
I guess this is in a way the same as putting a wrapper adapter which is achieved in gson by TypeAdapterRuntimeTypeWrapper.java If you look at the implementation of this function it does not do any specific logic in the read part. In the write part it does look at the type of the object and then makes an appropriate decision. @anthonycr , do you think we should add a field level support for something like this? The implementation in #56 is not entirely going to solve this case. |
Problem Statement : While parsing the model object, if any class which has subclasses is being used as a field, and its type is known at runtime, stag will not be able to get the corresponding type adapter, and hence it will not able to serialize the fields of the subtypes/subclasses.
Solution : Since the type is known at runtime, we have to fallback to gson to parse that particular field.
Proposed Fix : We can have another annotation named @WriteRuntimeType, and the if the classes which has subclasses or subtypes is being used as a field in another model should be annotated with this. This will enable stag to dynamically fallback to gson for parsing such fields.
@anthonycr Will this work ?
The text was updated successfully, but these errors were encountered: