Skip to content

Commit

Permalink
refactor: apply latest changes to the avro schema parser (#623)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicmatatjahu authored Sep 23, 2022
1 parent 6fc8b21 commit 4580db5
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 21 deletions.
24 changes: 17 additions & 7 deletions src/schema-parser/avro-schema-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ const typeMappings: Record<string, JSONSchema7TypeName> = {
uuid: 'string',
};

function commonAttributesMapping(avroDefinition: AvroSchema, jsonSchema: v2.AsyncAPISchemaDefinition, isTopLevel: boolean): void {
function commonAttributesMapping(avroDefinition: AvroSchema, jsonSchema: v2.AsyncAPISchemaDefinition, recordCache: { [key:string]: AsyncAPISchema }): void {
if (avroDefinition.doc) jsonSchema.description = avroDefinition.doc;
if (avroDefinition.default !== undefined) jsonSchema.default = avroDefinition.default;

const fullyQualifiedName = getFullyQualifiedName(avroDefinition);
if (isTopLevel && fullyQualifiedName !== undefined) {
if (fullyQualifiedName !== undefined && recordCache[fullyQualifiedName]) {
jsonSchema['x-parser-schema-id'] = fullyQualifiedName;
}
}
Expand Down Expand Up @@ -180,7 +180,9 @@ function additionalAttributesMapping(typeInput: any, avroDefinition: AvroSchema,
setAdditionalAttribute('minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'multipleOf');
break;
case 'string':
jsonSchema.format = avroDefinition.logicalType;
if (avroDefinition.logicalType) {
jsonSchema.format = avroDefinition.logicalType;
}
setAdditionalAttribute('pattern', 'minLength', 'maxLength');
break;
case 'array':
Expand All @@ -207,14 +209,14 @@ function validateAvroSchema(avroDefinition: AvroSchema): void | never {
* @param key String | Undefined - the fully qualified name of an avro record
* @param value JsonSchema - The json schema from the avro record
*/
function cacheAvroRecordDef(cache: {[key:string]: AsyncAPISchema}, key: string, value: AsyncAPISchema): void {
function cacheAvroRecordDef(cache: { [key:string]: AsyncAPISchema }, key: string, value: AsyncAPISchema): void {
if (key !== undefined) {
cache[key] = value;
}
}

async function convertAvroToJsonSchema(avroDefinition: AvroSchema , isTopLevel: boolean, recordCache: Map<string, v2.AsyncAPISchemaDefinition> | any = {}): Promise<v2.AsyncAPISchemaDefinition> {
const jsonSchema: v2.AsyncAPISchemaDefinition = {};
let jsonSchema: v2.AsyncAPISchemaDefinition = {};
const isUnion = Array.isArray(avroDefinition);

if (isUnion) {
Expand Down Expand Up @@ -266,12 +268,20 @@ async function convertAvroToJsonSchema(avroDefinition: AvroSchema , isTopLevel:
}
case 'record': {
const propsMap = await processRecordSchema(avroDefinition, recordCache, jsonSchema);
cacheAvroRecordDef(recordCache, getFullyQualifiedName(avroDefinition), propsMap);
jsonSchema.properties = Object.fromEntries(propsMap.entries());
break;
}
default: {
const cachedRecord = recordCache[getFullyQualifiedName(avroDefinition)];
if (cachedRecord) {
jsonSchema = cachedRecord;
}
break;
}
}

commonAttributesMapping(avroDefinition, jsonSchema, isTopLevel);
commonAttributesMapping(avroDefinition, jsonSchema, recordCache);
additionalAttributesMapping(type, avroDefinition, jsonSchema);

return jsonSchema;
Expand All @@ -296,7 +306,7 @@ async function processRecordSchema(avroDefinition: AvroSchema, recordCache: Reco
const def = await convertAvroToJsonSchema(field.type, false, recordCache);

requiredAttributesMapping(field, jsonSchema, field.default !== undefined);
commonAttributesMapping(field, def, false);
commonAttributesMapping(field, def, recordCache);
additionalAttributesMapping(field.type, field, def);

propsMap.set(field.name, def);
Expand Down
67 changes: 67 additions & 0 deletions test/schema-parser/avro/asyncapi-avro-148-1.9.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"schemaFormat": "application/vnd.apache.avro;version=1.9.0",
"payload": {
"type":"record",
"name":"RecordWithReferences",
"namespace":"com.example",
"fields":[
{
"name":"Record1",
"type":{
"type":"record",
"name":"Record1",
"doc":"Reused in other fields",
"fields":[
{
"name":"string",
"type":"string",
"doc":"field in Record1"
}
]
}
},
{
"name":"FieldThatDefineRecordInUnion",
"type":[
"null",
{
"type":"record",
"name":"RecordDefinedInUnion",
"namespace":"com.example.model",
"doc":"",
"fields":[
{
"name":"number",
"type":"long",
"doc":"field in RecordDefinedInUnion",
"minimum": 0,
"maximum": 2
}
]
}
],
"default":null
},
{
"name":"FieldThatReuseRecordDefinedInUnion",
"type":[
"null",
"com.example.model.RecordDefinedInUnion"
],
"default":null
},
{
"name":"FieldThatReuseRecord1",
"type":[
"null",
"Record1"
],
"default":null
},
{
"name": "simpleField",
"type": "string"
}
]
}
}
Loading

0 comments on commit 4580db5

Please sign in to comment.