KaiZen-OpenApi-Parser icon indicating copy to clipboard operation
KaiZen-OpenApi-Parser copied to clipboard

Unable to Get Array Items' Ref

Open dillonredding opened this issue 5 years ago • 9 comments

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 avatar Apr 02 '19 16:04 dillonredding

@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.

tedepstein avatar Apr 02 '19 19:04 tedepstein

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"));

dillonredding avatar Apr 02 '19 19:04 dillonredding

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.

dillonredding avatar Apr 02 '19 20:04 dillonredding

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 avatar Apr 03 '19 13:04 dillonredding

@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:

  1. 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.

  2. Something is fundamentally broken in JSON Overlay and/or KaiZen Parser, which seems unlikely because it's working in our projects.

  3. 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.

tedepstein avatar Apr 03 '19 17:04 tedepstein

@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 avatar Apr 03 '19 17:04 tedepstein

@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 avatar Apr 03 '19 20:04 dillonredding

@dillonredding I am doing a similar code generation tool to what you referred to above. Did you ever solve this issue?

ghost avatar Nov 13 '20 21:11 ghost

@pconrey No, I eventually dropped this effort since it ultimately contradicted some fundamental principles of REST architecture

dillonredding avatar Nov 13 '20 21:11 dillonredding