Skip to content

Commit 4947bd4

Browse files
bieluclaude
andcommitted
fix: read 2.x Avro payloads in the local reference fallback
Adds LocalAvroPayloadReference_NotInWorkspace_ResolvesPayload for 2.6.0 and 3.0.0, as requested in review. The 2.x case failed. For a 2.x document, the whole-document stream that the local fallback reads is the upgraded document serialized as 3.0, so an Avro payload appears there as a Multi Format Schema Object ({ schemaFormat, schema }). The 2.x loader read it as a JSON Schema and reported "schemaFormat/schema is not a valid property". The 2.x reader now uses the 3.x Multi Format Schema loader for that fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 062ca41 commit 4947bd4

3 files changed

Lines changed: 66 additions & 9 deletions

File tree

‎src/ByteBard.AsyncAPI.Readers/V2/AsyncApiMessageDeserializer.cs‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,6 @@ public static IAsyncApiSchema LoadAvroPayload(ParseNode n)
7373
return LoadPayload(n, "application/vnd.apache.avro");
7474
}
7575

76-
/// <summary>
77-
/// 2.x has no Multi Format Schema Object; the schema format lives on the message, so a payload read on its own is a JSON Schema.
78-
/// </summary>
79-
public static AsyncApiMultiFormatSchema LoadMultiFormatSchemaPayload(ParseNode n)
80-
{
81-
return new AsyncApiMultiFormatSchema { Schema = LoadJsonSchemaPayload(n) };
82-
}
83-
8476
private static IAsyncApiSchema LoadPayload(ParseNode n, string format)
8577
{
8678
if (n == null)

‎src/ByteBard.AsyncAPI.Readers/V2/AsyncApiV2VersionService.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public AsyncApiV2VersionService(AsyncApiDiagnostic diagnostic)
3636
[typeof(AsyncApiAvroSchema)] = AsyncApiAvroSchemaDeserializer.LoadSchema,
3737
[typeof(AsyncApiJsonSchema)] = AsyncApiV2Deserializer.LoadJsonSchemaPayload,
3838
[typeof(AsyncApiAvroSchema)] = AsyncApiV2Deserializer.LoadAvroPayload,
39-
[typeof(AsyncApiMultiFormatSchema)] = AsyncApiV2Deserializer.LoadMultiFormatSchemaPayload,
39+
// 2.x has no Multi Format Schema Object. Only the local reference fallback asks for one, and it reads the document after the upgrade to 3.0.
40+
[typeof(AsyncApiMultiFormatSchema)] = AsyncApiV3Deserializer.LoadMultiFormatSchema,
4041
[typeof(AsyncApiSecurityScheme)] = AsyncApiV2Deserializer.LoadSecurityScheme,
4142
[typeof(AsyncApiServer)] = AsyncApiV2Deserializer.LoadServer,
4243
[typeof(AsyncApiServerVariable)] = AsyncApiV2Deserializer.LoadServerVariable,

‎test/ByteBard.AsyncAPI.Tests/Models/AsyncApiReference_Should.cs‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,70 @@ public void LocalPayloadReference_NotInWorkspace_ResolvesPayload(string version)
263263
payload.Schema.As<AsyncApiJsonSchema>().Type.Should().Be(SchemaType.String);
264264
}
265265

266+
// A local Avro payload reference that is not a registered component is resolved by falling back to the whole document.
267+
[TestCase("2.6.0")]
268+
[TestCase("3.0.0")]
269+
public void LocalAvroPayloadReference_NotInWorkspace_ResolvesPayload(string version)
270+
{
271+
var yaml = version.StartsWith("2")
272+
? """
273+
asyncapi: 2.6.0
274+
info:
275+
title: test
276+
version: 1.0.0
277+
channels:
278+
workspace:
279+
publish:
280+
message:
281+
schemaFormat: application/vnd.apache.avro;version=1.9.0
282+
payload:
283+
$ref: '#/components/messages/shared/payload'
284+
components:
285+
messages:
286+
shared:
287+
schemaFormat: application/vnd.apache.avro;version=1.9.0
288+
payload:
289+
type: record
290+
name: User
291+
fields:
292+
- name: name
293+
type: string
294+
"""
295+
: """
296+
asyncapi: 3.0.0
297+
info:
298+
title: test
299+
version: 1.0.0
300+
channels:
301+
workspace:
302+
messages:
303+
message:
304+
payload:
305+
$ref: '#/components/messages/shared/payload'
306+
components:
307+
messages:
308+
shared:
309+
payload:
310+
schemaFormat: application/vnd.apache.avro;version=1.9.0
311+
schema:
312+
type: record
313+
name: User
314+
fields:
315+
- name: name
316+
type: string
317+
""";
318+
319+
var doc = new AsyncApiStringReader().Read(yaml, out var diagnostic);
320+
321+
diagnostic.Errors.Should().BeEmpty();
322+
var payload = doc.Channels["workspace"].Messages.Values.First().Payload;
323+
payload.Should().BeOfType<AsyncApiMultiFormatSchemaReference>();
324+
payload.SchemaFormat.Should().StartWith("application/vnd.apache.avro");
325+
var record = payload.Schema.As<AsyncApiAvroSchema>().As<AvroRecord>();
326+
record.Name.Should().Be("User");
327+
record.Fields.Should().ContainSingle().Which.Name.Should().Be("name");
328+
}
329+
266330
[Test]
267331
public void V2_ReferencePointers()
268332
{

0 commit comments

Comments
 (0)