Skip to content

add java.lang.reflect.Type to deserialize API #331

Description

@xiazuojie

Describe the proposal

As discussed #293 , TypeRef<T> was added to support deserialization of generic types.
However, instances of TypeRef<T> can only be statically (during compilation) created. There are occasions when generic types need to be dynamically created. I suggest adding the following method to deserialize API to support such cases.
<T> T deserialize(byte[] data, java.lang.reflect.Type type) throws IOException

Activity

  1. artursouza commented on Aug 31, 2020

    @artursouza
    Contributor

    Can you provide an example of a scenario that will not work with the current API?

    BTW, this change is not only to the deserialize API, it will also propagate to every method in our API that invoke deserialize() internally. Today, users can also have their own serialization done outside the SDK and send byte[] as input - in those cases, the internal serialization is skipped.

  2. xiazuojie commented on Sep 8, 2020

    @xiazuojie
    ContributorAuthor

    My scenario is that users' code relies on some other API that works with java.lang.reflect.Type. I need to translate it into Dapr's DaprObjectSerializer API.
    With current implementation, it's not possible to do the translation - users' code has to rely on dapr-sdk directly, which is not desired.

  3. artursouza commented on Sep 8, 2020

    @artursouza
    Contributor

    The default serializer uses java.lang.reflect.Type. See type.getType() in the implementation below. Is this what you need?

      public <T> T deserialize(byte[] content, TypeRef<T> type) throws IOException {
        return deserialize(content, OBJECT_MAPPER.constructType(type.getType()));
      }
    
  4. xiazuojie commented on Sep 9, 2020

    @xiazuojie
    ContributorAuthor

    The default serializer uses java.lang.reflect.Type. See type.getType() in the implementation below. Is this what you need?

      public <T> T deserialize(byte[] content, TypeRef<T> type) throws IOException {
        return deserialize(content, OBJECT_MAPPER.constructType(type.getType()));
      }
    

    Not what I want. I need the following api.
    <T> T deserialize(byte[] data, java.lang.reflect.Type type) throws IOException

    Note that one cannot create an instance of TypeRef<T> from java.lang.reflect.Type dynamically.

  5. artursouza commented on Sep 17, 2020

    @artursouza
    Contributor

    All of the Dapr's Java SDK relies on Class or TypeRef. If your code relies on Type directly, it is not just the serializer but also all of the APIs in the SDK. We can add overloaded methods for Type everywhere or we can add a new method in TypeRef to do what you want. In this case, the generic type would be Object since there is no generic type in Type:

      public static TypeRef<Object> get(Type type) {
        return new TypeRef(type) {};
      }
    

    This seems to provide a more concise API than giving two deserialize methods to be implemented by applications. When designing an API we need to be mindful not to make changes with only one app in mind, so I am trying to generalize your ask to keep the SDK relevant to other apps too.

  6. artursouza commented on Oct 7, 2020

    @artursouza
    Contributor

    In summary: I am not in favor of adding an overloaded deserialize method with Type as input since it would impact all of the SDK APIs.

    The same can be accomplished with adding the new builder method in TypeRef where type is given as input (like in the comment above). This way there is a way to convert between Type and TypeRef back and forth, allowing user code that relies on Type only to still make use of the Dapr SDK. This solution would also not be a breaking change.

  7. pkedy commented on Jan 23, 2021

    @pkedy
    Member

    Hi @xiazuojie! I hope #449 addresses this for you. It will be in the next release. As @artursouza mentioned we opted to put the handling of java.lang.reflect.Type in TypeRef to avoid overloading the DaprObjectSerializer interface and keeping it small.

    For anyone following along, one discovery we had was that Java can create an instance of TypeRef<T> even if the parameter does not reference <T>. I assume it does this by inferring it from the type of the variable you are assigning it to. I was surprised this worked so I thought I'd mention here.

  8. mukundansundar commented on Jan 23, 2021

    @mukundansundar
    Contributor

    closed by #449

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions