Skip to content

fix: avro schema union types generate object type #250

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

Merged
merged 6 commits into from
Mar 1, 2022

Conversation

CameronRushton
Copy link
Member

@CameronRushton CameronRushton commented Mar 1, 2022

Problem
When specifying multiple (union) types in an avro schema, we used to blindly use the x-schema-parser-id as the type, but a union type is technically a schema itself, so the x-schema-parser-id, instead of being a type, is an anonymous schema.
Union type example

payload:
  name: "JobOrder"
  namespace: "com.example.api.jobOrder"
  doc: "JobOrder"
  type: "record"
  fields:
    - name: "jobOrderLongDescription"
        doc: "JobOrderLongDescription"
        type:
        - "null"
        - "string"

Generated code sample

public JobOrder (
  String jobOrderId, 
  <anonymous-schema-2> jobOrderDescription, 
  <anonymous-schema-5> jobOrderLongDescription, 
  String jobOrderNumber)

Solution
Similar to the function in all.js, getMessagePayloadType, fixType has an order of which location has the correct type (There's a chance there's some code duplication here, but we dont have tests that cover the necessary branches so I'm holding off on it for now).
The order of preference for getting the type is something like this from most preferred (type) to least (parser-id):

  • The 'type' field on the schema (that's not a union)
  • (new) allOf, anyOf, oneOf fields, of which the type shall be Object
  • x-schema-parser-id
    There's also cases for enums and arrays but I'm omitting them in this description.

This works because each value in our type field (the union)...

type:
        - "null"
        - "string"

... is a schema itself and the generator assigns these tiny schemas to an anyOf() keyword. This makes sense in all cases where type isn't specified, so the user can still have an anyOf() that they defined themselves and we still need to say it's an object. The only potential difference is between json schema and avro schema. In avro, we must say it's an Object and we can't be smart about choosing for the user. In json schema, we could potentially guess (iirc).

Additionally, the generated toString() method now calls toString() on any Object type within the toString().

public String toString() {
		return "JobOrder ["
		+ " jobOrderId: " + jobOrderId
		+ " jobOrderDescription: " + jobOrderDescription.toString()
		+ " jobOrderLongDescription: " + jobOrderLongDescription.toString()
		+ " ]";
	}

Related issue(s)
Resolves #247

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 1, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@CameronRushton CameronRushton merged commit a5d6d23 into asyncapi:master Mar 1, 2022
@asyncapi-bot
Copy link
Contributor

🎉 This PR is included in version 0.12.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Successfully merging this pull request may close these issues.

AVRO schema unions code generation issue
3 participants