Skip to content
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

Examples not reads when format: byte #1630

Closed
gervaisb opened this issue Nov 30, 2021 · 8 comments
Closed

Examples not reads when format: byte #1630

gervaisb opened this issue Nov 30, 2021 · 8 comments
Assignees

Comments

@gervaisb
Copy link

Hello there,

From the openapi-style-validator project, we have an issue with properties of type string and format byte where the example is not read: OpenAPITools/openapi-style-validator#132

Schema:

  schemas:
    Response:
      required:
        - content
      properties:
        content:
          type: string
          format: byte
          example: "VGhpc1Nob3VsZFBhc3MK"

Expected:
An OpenAPI with example set for the content property.

Actual:
example is null.

We do not know if this is expected behaviour or an issue on the parser, can someone tell us more on that "issue" ?

Thanks

@gervaisb
Copy link
Author

gervaisb commented Nov 30, 2021

After digging into the parser, I see that the value is skipped in this part of the code:

    protected byte[] cast(Object value) {
        if (value != null) {
            try {
                if (value instanceof byte[]) {
                    return (byte[]) value;
                }
            } catch (Exception e) {
            }
        }
        return null;
    }

io/swagger/v3/oas/models/media/ByteArraySchema.java:50

The value is not null but is a String not a byte[] then the method returns null which is set as example value.

@frantuma frantuma self-assigned this Mar 22, 2022
@frantuma
Copy link
Member

@gervaisb thanks for reporting this. It is a bit tricky and has been addressed in #1682, and will be available in next release.

TLDR

Probably in your case the best option is to set either system property or env variable swaggerParserBinaryAsString to any non null value. This will result in parser deserializing schemas with type=string and format=binary or format=byte as StringSchema` instances, and string provided in example will be available as is.

Short background

Swagger Core "models" - also for historical reasons - provides a hierarchy of classes representing Json Schema constructs; depending on type and format, Swagger Parser deserializes schemas into one of these classes, which define types to be used for fields like default, enum, etc, including example. If the data type is different, like in ByteArraySchema just updated in scope of this ticket, the value is converted (if possible) into the target datatype. In this case the example: whateverbinarystring would be converted into a byte array (via value.toString().getBytes(), opinionated, an alternative could be considering the value be Base64 encoded). During serialization (handled by swagger-core / Jackson) this binary value is serialized differently in Json (converted to string) and YAML (using YAML tag to represent binary). which might result in inconsistent/wrong behaviour.

Given that there is not much added value in using specialized classes ByteArraySchema and BinarySchema, as mentioned above #1682 introduces option to deserialize into a StringSchema, which provides a more consistent behaviour. Option is not activated by default for backward compatibility

@gracekarina
Copy link
Contributor

refs: swagger-api/swagger-core#4147

@gervaisb
Copy link
Author

Thanks @frantuma for the explanation. I am just wondering why you can't try the conversion from the ByteArraySchema class itself?

protected byte[] cast(Object value) {
    if (value != null) {
        try {
            if (value instanceof byte[]) {
                return (byte[]) value;
            } else if (value instanceof String) {
                return ((String) value).getBytes()
            }
        } catch (Exception e) {
        }
    }
    return null;
}

@frantuma
Copy link
Member

@gervaisb

we have added indeed such conversion in swagger-api/swagger-core#4147, therefore you can use it if it fits your needs (by using parser "as is" , with no swaggerParserBinaryAsString property/env set).

The first possible issue with this approach is that the conversion / data binding is opinionated, as it uses getBytes() to encode the string into bytes, while e.g. the serialized string could be meant to be a Base64 encoded representation of the bytes (Jackson e.g. uses Base64 for default binding of string to byte[])

Another issue is serialization of the parsed string, in this case the serialized value will be encoded in Base64, resulting in a different string from the one parsed.

We might choose to try using Base64 in the cast method above, but again this would be an opinionated choice, given also that e.g. example is of any type in OAS 3.0, possibly including any encoding/representation of binary values

An additional issue is serialization to YAML; YAML is capable to represent binary using tags, and indeed default serialization uses that, therefore a YAML version of the same spec, with the same string value in example as the one in JSON version, would not be parsed correctly (would actually break).

example: !!binary |-
  Y2FjY2E=

We could further address the points above by e.g. providing more options and addressing the different cases, but on top of adding quite some complexity and being not trivial, the expected behaviour would be dependent on the specific spec.

@gervaisb
Copy link
Author

Thanks for your work. Any idea when it will be released?

@frantuma
Copy link
Member

no fixed ETA but probably within first week of April

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants