Closed yasammez closed 6 years ago
Thanks for reporting this issue @fischmax. Could you try using the v1 package and check if you get the same error? JsonSchemaGenerator is deprecated. To use the v1 package you have to checkout the project to your local machine and install it. Let me know if you have any problem. Thanks!
Thanks for your fast reply, it is much appreciated!
I just tested with v1 and still get the same error. For a minimal (non-)working example, add
private List<Optional<URI>> uris;
to the example Product
class. I get the following stack trace:
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class at com.github.reinert.jjschema.v1.PropertyWrapper.
(PropertyWrapper.java:77) at com.github.reinert.jjschema.v1.CustomSchemaWrapper.processProperties(CustomSchemaWrapper.java:134) at com.github.reinert.jjschema.v1.CustomSchemaWrapper. (CustomSchemaWrapper.java:60) at com.github.reinert.jjschema.v1.CustomSchemaWrapper. (CustomSchemaWrapper.java:47) at com.github.reinert.jjschema.v1.CustomSchemaWrapper. (CustomSchemaWrapper.java:43) at com.github.reinert.jjschema.v1.SchemaWrapperFactory.createWrapper(SchemaWrapperFactory.java:69) at com.github.reinert.jjschema.v1.SchemaWrapperFactory.createWrapper(SchemaWrapperFactory.java:45) at com.github.reinert.jjschema.v1.SchemaWrapperFactory.createWrapper(SchemaWrapperFactory.java:37) at com.github.reinert.jjschema.v1.JsonSchemaV4Factory.createSchema(JsonSchemaV4Factory.java:36) at Entry.main(Entry.java:9)
I checked the issue. The solution is not trivial...
The issue isn't (only) that the code doesn't handle recursive generics.
It's indeed that the code (1) only handles generics of collections - it should handle generics of any class - and (2) doesn't handle recursive generics.
You can check it in PropertyWrapper class (L73-79).
Unfortunately I do not have the available time to solve it. I encourage you to go deep in this issue and fix it.
Contributions are always welcome!
At my workplace, the decision was made to deploy a self-written schema generator instead, which had the same problem which I fixed in a rather ad-hoc way. I am pretty sure I am not allowed to dump the whole thing here, but the important part is:
while (subtype instanceof ParameterizedType) {
if (Iterable.class.isAssignableFrom((Class<?>) ((ParameterizedType) subtype)
.getRawType()))
arrayDepth = arrayDepth + 1;
subtype = ((ParameterizedType) subtype).getActualTypeArguments()[0];
}
As you can see, this merely strips all other generics of the type (we have to deal mostly with wrappers like Optional<> which are not important to us in the JSON) and tracks an additional arrayDepth
field which is later used to wrap the thing in
{
'type':'array',
'items': { … }
}
blocks.
Recursion on the other hand is handled by tracking a list of visited types and inserting a { '$ref': <ID> }
at the appropriate point.
I will ask my employer if I may share the whole thing, depending on if you are even interested: the solution for the generics is probably only useful for us and a more general approach would be nice. But then, you never now what someone is going to do with generics, so it could be hard to anticipate everything.
I see. Recursion is already solved this way in JJSchema. Nested generics, however, is not handled. I appreciate your tip. Thanks.
File: JsonSchemaGenerator.java Method: processPropertyCollection Line: 205
How to reproduce: have a remote transfer object with nested generics, like List<Optional> or the like and call generateSchema with it. Expected result: a schema describing the input object. Actual result: ClassCastException. Reason: The method doesn't resolve the generic recursive, but only one level deep.