-
Notifications
You must be signed in to change notification settings - Fork 119
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
Converter for polymorphic types #1037
Comments
I'll start by saying you can probably get the effect you want by explicitly specifying the converter to use; use the Next, I'll point out that SmallRye Config does indeed support generic converters to an extent, though mostly it's done internally with certain fixed types (lists and arrays of objects, for example). So we're part way there already. Lastly, I will address the idea of full-blown generic converters. This has been discussed several times since the inception of this project IIRC, and is something that I think we would want to do but doing it right is pretty tricky. The implementation would probably require something like these interfaces: public interface GenericConverter1<T, U> {
T convert(String value, Converter<U> nestedConverter);
}
public interface GenericConverter2<T, U, V> {
T convert(String value, Converter<U> nestedConverter1, Converter<V> nestedConverter2);
}
// that's probably as far as we need to go, but we could take it further if needed... Then when we encounter a generic parameterized type, we can search for a converter with the correct parameters. As a trivial example, to support a converter for public class MyEntryConverter<U, V> implements GenericConverter2<Map.Entry<U, V>, U, V> {
public Map.Entry<T, U> convert(String value, Converter<U> nested1, Converter<V> nested2) {
String[] items = value.split(";", 2);
return Map.entry(nested1.convert(items[0]), nested2.convert(items[1]));
}
} The negatives with this design would be the ugliness of having multiple generic converter interfaces, and the increased complexity of searching for converters. On the other hand, it would allow our special-case converters (collections, |
I see. For what it's worth I'm trying to integrate smallrye config with our current projects, which are Scala projects. I'll give |
The problem with doing this in Java is not that we can't induce the higher-kinded converter type (in fact, we can and do in several cases), it's that the I guess an alternative to having multiple interfaces would be to require that the converter type have a constructor which accepts one converter for each generic type, so one converter instance is constructed per use site. This approach has a complexity and memory footprint tradeoff though. |
Actually I'm not quiet sure what you mean by this. I would understand if FooConverter were not type parameterized. But since it is: public class FooConverter<T extends Converter<T>> implements Converter<Foo<T>> {
@Override
public Foo<T> convert(String value) {
throw new IllegalStateException("aaah");
}
}
fails for
and
is not allowed for, I think, type erasure. I'll admit to not being great with java generics and reflection. Am I doing something obviously wrong here? Thank you |
I think you're saying I need to implement a Converter for every concrete type:
and
which does work. |
Right, it's not ideal but it does the job for limited cases. |
Right, essentially you're saying that
Right, when you give a class constant, you can't give type arguments (in other words, every class has only one |
I've realized fixing this at the Converter level with your suggested interfaces would not fix the issue at hand. A converter takes a single string. There is no way to pass to the converter an entire tree. If I have something like
I cannot lift this into a With the suggested implementation we can only lift primitives and things which can be constructed from a single string into a Foo. |
Correct; independent keys can be placed into the same group, but they're still independent. |
I'd like to read a string from the config into a Foo.
I have a Yaml of the form
and a class of the form
And I'd like to read the config into a Foo via an interface like so:
However, I get the error
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.IllegalArgumentException: SRCFG00013: No Converter registered for class com.socrata.config.Foo [in thread "main"]
As far as I can tell implementing a
Converter<Foo<T>>
is not possible. Is there any way to write aConverter<Foo<T>>
?I tried with something like
But the FooConverter is never used.
In summary I'd like to have an config interface with a field that is a parameterized type where the type parameter itself implements a Converter.
Thank you,
The text was updated successfully, but these errors were encountered: