1

If ElementType is a statically known type, it is "easy" to create a Type object representing a collection of ElementTypes:

Type listType = new TypeToken<ObservableList<ElementType>>(){}.getType();

But this is not possible here as my elementType is a dynamic value, only known at runtime:

@Override
public ListProperty<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
        JsonParseException {
    Type elementType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
    Type listType = // ??? create the type representing a ObservableList<elementType>
    ObservableList<?> list = context.deserialize(json, listType);
    return new SimpleListProperty<>(list);
}

Now I would like listType to represent an ObservableList<> which type parameter should be the value of elementType. Is there a way to do so?

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • I'm confused as to what `elementType` is referring to? What do you mean by _dynamic_? Where is it coming from? – Sotirios Delimanolis May 11 '16 at 01:26
  • @SotiriosDelimanolis I'm writing a custom JSON deserializer for some sort of list. The type of that list is given as a parameter `Type typeOfT` to my method. Now my deserializer is supposed to defer the work by deserializing as another kind of list, so I need to create the `typeOfT` for that other kind myself. – Joffrey May 11 '16 at 01:29
  • See [here](http://stackoverflow.com/a/25223817/438154). – Sotirios Delimanolis May 11 '16 at 01:30
  • @SotiriosDelimanolis This is exactly my problem indeed. – Joffrey May 11 '16 at 01:32

2 Answers2

1

If you have Guava, you can use their version of TypeToken which offers what you need:

static <T> TypeToken<ObservableList<T>> mapToken(TypeToken<T> typeParameter) {
    return new TypeToken<ObservableList<T>>() {}.where(new TypeParameter<T>() {}, typeParameter);
}

@Override
public ListProperty<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
        JsonParseException {
    Type elementType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
    Type listType = mapToken(TypeToken.of(elementType)).getType();
    ObservableList<?> list = context.deserialize(json, listType);
    return new SimpleListProperty<>(list);
}
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Thanks for the answer, but I'd rather not add a dependency on Guava just for this as I'm not already using it. – Joffrey Jun 11 '16 at 16:11
0

As suggested in this post, I ended up creating my own implementation of ParametrizedType:

private static class CustomParameterizedType implements ParameterizedType {

    private Type rawType;
    private Type ownerType;
    private Type[] typeArguments;

    private CustomParameterizedType(Type rawType, Type ownerType, Type... typeArguments) {
        this.rawType = rawType;
        this.ownerType = ownerType;
        this.typeArguments = typeArguments;
    }

    @Override
    public Type[] getActualTypeArguments() {
        return typeArguments;
    }

    @Override
    public Type getRawType() {
        return rawType;
    }

    @Override
    public Type getOwnerType() {
        return ownerType;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        CustomParameterizedType that = (CustomParameterizedType) o;
        return Objects.equals(rawType, that.rawType) &&
                Objects.equals(ownerType, that.ownerType) &&
                Arrays.equals(typeArguments, that.typeArguments);
    }

    @Override
    public int hashCode() {
        return Objects.hash(rawType, ownerType, typeArguments);
    }
}

And then I could use it this way:

@Override
public ListProperty<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
        JsonParseException {
    Type elementType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
    Type listType = new CustomParametrizedType(ObservableList.class, null, elementType);
    ObservableList<?> list = context.deserialize(json, listType);
    return new SimpleListProperty<>(list);
}
Community
  • 1
  • 1
Joffrey
  • 32,348
  • 6
  • 68
  • 100