Skip to content

Commit

Permalink
Fix schema generation for nullable Uri
Browse files Browse the repository at this point in the history
  • Loading branch information
dstelljes committed Oct 3, 2023
1 parent 50fa327 commit 69e8a5d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/Chr.Avro.Fixtures/Fixtures/NullableMemberClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class NullableMemberClass

public string ObliviousStringProperty { get; set; }

public Uri ObliviousUriProperty { get; set; }

public string[] ObliviousArrayOfStringsProperty { get; set; }

public List<string> ObliviousListOfStringsProperty { get; set; }
Expand All @@ -28,6 +30,10 @@ public class NullableMemberClass

public string? NullableStringProperty { get; set; }

public Uri UriProperty { get; set; }

public Uri? NullableUriProperty { get; set; }

public string[] ArrayOfStringsProperty { get; set; }

public string?[] ArrayOfNullableStringsProperty { get; set; }
Expand Down
6 changes: 2 additions & 4 deletions src/Chr.Avro/Abstract/BytesSchemaBuilderCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ public virtual SchemaBuilderCaseResult BuildSchema(Type type, SchemaBuilderConte
{
if (type == typeof(byte[]))
{
var bytesSchema = new BytesSchema();
Schema schema = new BytesSchema();

Schema schema = bytesSchema;

if (!type.IsValueType && NullableReferenceTypeBehavior == NullableReferenceTypeBehavior.All)
if (NullableReferenceTypeBehavior == NullableReferenceTypeBehavior.All)
{
if (!context.Schemas.TryGetValue(NullableType, out var nullSchema))
{
Expand Down
2 changes: 1 addition & 1 deletion src/Chr.Avro/Abstract/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public static IEnumerable<Func<ISchemaBuilder, ISchemaBuilderCase>> CreateDefaul
// built-ins:
builder => new DurationSchemaBuilderCase(),
builder => new TimestampSchemaBuilderCase(temporalBehavior),
builder => new UriSchemaBuilderCase(),
builder => new UriSchemaBuilderCase(nullableReferenceTypeBehavior),
builder => new UuidSchemaBuilderCase(),

// classes and structs:
Expand Down
6 changes: 2 additions & 4 deletions src/Chr.Avro/Abstract/StringSchemaBuilderCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ public virtual SchemaBuilderCaseResult BuildSchema(Type type, SchemaBuilderConte
{
if (type == typeof(string))
{
var stringSchema = new StringSchema();
Schema schema = new StringSchema();

Schema schema = stringSchema;

if (!type.IsValueType && NullableReferenceTypeBehavior == NullableReferenceTypeBehavior.All)
if (NullableReferenceTypeBehavior == NullableReferenceTypeBehavior.All)
{
if (!context.Schemas.TryGetValue(NullableType, out var nullSchema))
{
Expand Down
32 changes: 29 additions & 3 deletions src/Chr.Avro/Abstract/UriSchemaBuilderCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ namespace Chr.Avro.Abstract
/// </summary>
public class UriSchemaBuilderCase : SchemaBuilderCase, ISchemaBuilderCase
{
/// <summary>
/// Initializes a new instance of the <see cref="UriSchemaBuilderCase" /> class.
/// </summary>
/// <param name="nullableReferenceTypeBehavior">
/// The behavior to use to determine nullability of reference types.
/// </param>
public UriSchemaBuilderCase(NullableReferenceTypeBehavior nullableReferenceTypeBehavior)
{
NullableReferenceTypeBehavior = nullableReferenceTypeBehavior;
}

/// <summary>
/// Gets the behavior used to determine nullability of reference types.
/// </summary>
public NullableReferenceTypeBehavior NullableReferenceTypeBehavior { get; }

/// <summary>
/// Builds a <see cref="StringSchema" />.
/// </summary>
Expand All @@ -21,18 +37,28 @@ public virtual SchemaBuilderCaseResult BuildSchema(Type type, SchemaBuilderConte
{
if (type == typeof(Uri))
{
var uriSchema = new StringSchema();
Schema schema = new StringSchema();

if (NullableReferenceTypeBehavior == NullableReferenceTypeBehavior.All)
{
if (!context.Schemas.TryGetValue(NullableType, out var nullSchema))
{
context.Schemas.Add(NullableType, nullSchema = new NullSchema());
}

schema = new UnionSchema(new[] { nullSchema, schema });
}

try
{
context.Schemas.Add(type, uriSchema);
context.Schemas.Add(type, schema);
}
catch (ArgumentException exception)
{
throw new InvalidOperationException($"A schema for {type} already exists on the schema builder context.", exception);
}

return SchemaBuilderCaseResult.FromSchema(uriSchema);
return SchemaBuilderCaseResult.FromSchema(schema);
}
else
{
Expand Down
29 changes: 28 additions & 1 deletion tests/Chr.Avro.Tests/Abstract/SchemaBuilderShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ public void BuildClassesWithNullableProperties()
type => Assert.Equal(typeof(object), type),
type => Assert.Equal(typeof(Guid), type),
type => Assert.Equal(typeof(List<string>), type),
type => Assert.Equal(typeof(Guid?), type));
type => Assert.Equal(typeof(Guid?), type),
type => Assert.Equal(typeof(Uri), type));

Assert.Collection(
schema.Fields,
Expand Down Expand Up @@ -440,6 +441,22 @@ public void BuildClassesWithNullableProperties()
});
},
field =>
{
Assert.Equal(nameof(NullableMemberClass.NullableUriProperty), field.Name);

var union = Assert.IsType<UnionSchema>(field.Type);
Assert.Collection(
union.Schemas,
child =>
{
Assert.IsType<NullSchema>(child);
},
child =>
{
Assert.IsType<StringSchema>(child);
});
},
field =>
{
Assert.Equal(nameof(NullableMemberClass.ObliviousArrayOfStringsProperty), field.Name);

Expand Down Expand Up @@ -487,9 +504,19 @@ public void BuildClassesWithNullableProperties()
Assert.IsType<StringSchema>(field.Type);
},
field =>
{
Assert.Equal(nameof(NullableMemberClass.ObliviousUriProperty), field.Name);
Assert.IsType<StringSchema>(field.Type);
},
field =>
{
Assert.Equal(nameof(NullableMemberClass.StringProperty), field.Name);
Assert.IsType<StringSchema>(field.Type);
},
field =>
{
Assert.Equal(nameof(NullableMemberClass.UriProperty), field.Name);
Assert.IsType<StringSchema>(field.Type);
});
Assert.Null(schema.LogicalType);
Assert.Equal(typeof(NullableMemberClass).Name, schema.Name);
Expand Down

0 comments on commit 69e8a5d

Please sign in to comment.