KaiZen-OpenApi-Parser
KaiZen-OpenApi-Parser copied to clipboard
Unable to Get Array Items' Ref
Perhaps I'm missing something, but I can't seem to get the reference of an array's items.
Given the spec:
openapi: 3.0.2
# ...
components:
schemas:
event:
type: object
properties:
invitees:
type: array
items:
$ref: '#/components/schemas/user'
user:
type: object
properties:
name:
type: string
This returns false
:
Overlay.of(model.getSchema("event").getProperty("invitees")).isReference("items");
@dillonredding , that behavior definitely looks wrong, not consistent with what's described in our docs here.
How are you parsing the model? From a string, a file, URI or URL? Is there anything between the parse and the isReference
call that could account for loss of reference information?
FYI, we will most likely not have bandwidth on the RepreZen team to look at this for a while. If you are inclined to dig into the code yourself and try to find the root cause of this, we'd appreciate the help. If not, I'm sorry we couldn't turn around a quick fix or a better explanation at this time.
I'm reading it from a file. I tried removing any intermediary processing with the following example, but still get the same result.
var resource = this.getClass().getResource("/api-spec.yaml");
var file = new File(resource.getFile());
var model = new OpenApi3Parser().parse(file);
var property = model.getSchema("event").getProperty("invitees");
assertFalse(Overlay.of(property).isReference("items"));
I get the same parsing as a string
var resource = this.getClass().getResource("/api-spec.yaml");
val contents = Files.readString(Paths.get(resource.toURI()));
var model = new OpenApi3Parser().parse(contents);
// ...
a URI
var resource = this.getClass().getResource("/api-spec.yaml");
var model = new OpenApi3Parser().parse(resource.toURI());
// ...
and a URL
var resource = this.getClass().getResource("/api-spec.yaml");
var model = new OpenApi3Parser().parse(resource.toURI().toURL());
// ...
I might be able to take a stab at digging into the code.
This issue appears to be in Overlay#getReference(String)
:
public Reference getReference(String key) {
if (overlay instanceof PropertiesOverlay) {
return getPropertyReference(key);
} else if (overlay instanceof MapOverlay) {
return getMapReference(key);
} else {
return null;
}
}
In my case, Overlay.of(model.getSchema("event").getProperty("invitees"))
returns an Overlay<Schema>
, meaning the overlay
field is an instance of SchemaImpl
. Therefore, calling getReference
returns null
, causing isReference
to return false
.
I'll keep digging and try to figure out a fix. Until then, any recommendations, @tedepstein?
@dillonredding , many of the classes are generated by JSON Overlay; and there aren't any docs available on that project yet. I don't really have intimate knowledge of this code, and don't have capacity on the development team right now to look at this.
I've been digging into it for a while now, just trying to get my head around it. I was hoping to find a recent change that might account for the breakage, because this seems like the kind of thing that "must have worked at some point." Subschemas, like the items
subschema you've referenced in your input, are a very common thing to represent using $ref
.
Seeing that this is not working in your case would seem to mean either:
-
Your code is not doing this right, which also means that our docs are wrong. I'm sorry to say, but I really wouldn't be in a position to know if this is the case.
-
Something is fundamentally broken in JSON Overlay and/or KaiZen Parser, which seems unlikely because it's working in our projects.
-
Something is locally broken in this particular case, but we don't know why. Seems the most likely case, I just don't have bandwidth at this moment to research it completely.
Again, sorry that I cannot be of more immediate help. We'll get to it as soon as we can.
@dillonredding , just a quick question: Why do you need to inspect the $ref
?
I imagine you have a good reason. But in my earlier research, it looked like most of our use cases lean pretty heavily on automatic resolution of refs, and then don't care about the original $ref value, only the resolved object graph.
I don't have high confidence in this theory, because I haven't looked comprehensively at all of our code that uses KaiZen Parser. But if this is largely correct, that might explain why something that seems pretty fundamental is broken, and has been for some time. And then we can feel a little more comfortable just pushing forward with a fix.
@tedepstein, I'm creating a Maven plugin that will generate Java classes based on the schemas in an OpenAPI spec. In the case of an array
property, the field would be a List
and I'd like to inspect the $ref
for generating the type parameter.
In my original example, you'd get a class for the user
schema
// package and imports...
public class User {
private String name;
// getters, setters, toString, etc...
}
And the class for the event
schema would look something like
public class Event {
private List<User> invitees;
}
If the items aren't a reference and, say, of type string
, then you'd get a List<String>
.
@dillonredding I am doing a similar code generation tool to what you referred to above. Did you ever solve this issue?
@pconrey No, I eventually dropped this effort since it ultimately contradicted some fundamental principles of REST architecture