Releases: ch-robinson/dotnet-avro
9.2.0
This minor release addresses a compatibility issue and fixes a serialization bug on Apple Silicon:
-
Chr.Avro.Confluent now targets Confluent.Kafka and Confluent.SchemaRegistry 1.9.3 to address an unexpected API change (#229, #230).
-
In previous versions, attempting to serialize negative
Duration
s would silently write zero instead of throwingOverflowException
when running on M1 processors (and possibly other ARM targets).
9.1.1
This patch release fixes a CLI issue introduced in 8.0.0:
dotnet avro registry-test
would fail with an unhandled exception (#223).
9.1.0
This minor release adds support for an additional System.ComponentModel attribute:
-
When generating record schemas, Chr.Avro uses the
[Description]
attribute (if present) to derive descriptions for records and fields (#219, h/t @thomasbrueggemann). For example, given the following class:[Description("Represents an object in the graph.")] public class Node { [Description("The unique identifier of the node.")] public Guid Id { get; set; } }
The schema builder would generate:
{ "name": "Node", "type": "record", "description": "Represents an object in the graph.", "fields": [{ "name": "Id", "type": { "type": "string", "logicalType": "uuid" }, "description": "The unique identifier of the node." }] }
9.0.0
This major release includes improvements to component model and data contract attribute usage.
Breaking changes
-
When generating schemas for
decimal
, Chr.Avro attempts to use the[Range]
attribute to infer decimal precision and scale (#216). For example, given the following class:public class SensorReading { [Range(typeof(decimal), "0.000", "1.000", ConvertValueInInvariantCulture = true)] public decimal Value { get; set; } }
The schema builder would generate:
{ "name": "SensorReading", "type": "record", "fields": [{ "name": "Value", "type": { "type": "bytes", "logicalType": "decimal" "precision": 4, "scale": 3 } }] }
If precision and scale cannot be inferred, Chr.Avro will fall back to the defaults (29 and 14, respectively).
-
When serializing enum types to
"string"
schemas, Chr.Avro uses the[EnumMember]
attribute value if one is set (#217). This matches the behavior of the schema builder for enum types when behavior is set toSymbolic
(the default).
8.2.0
This minor release updates dependency versions:
- Chr.Avro.Confluent targets Confluent.Kafka and Confluent.SchemaRegistry 1.9.x.
8.1.1
This patch release fixes an issue with data contract attribute handling:
- Serdes for fields with
[DataMember]
and[EnumMember]
attributes failed when the name or value was not set explicitly.
8.1.0
8.0.2
This patch release fixes an issue with default value representation:
- Default values specified with the
[DefaultValue]
attribute or directly withObjectDefaultValue<TValue>
were unable to be written by the JSON schema writer (#199, #200, h/t @nicodeslandes).
8.0.1
8.0.0
8.0.0 is a major release that includes a number of breaking changes and significant new features. Some of these have been in the works for over a year, and we’re excited to finally make them available.
Breaking changes
-
The type resolution framework has been removed, and the schema builder and the serializer builders now reflect on .NET types directly.
Before:
var typeResolver = new ReflectionResolver( memberVisibility: BindingFlags.Public | BindingFlags.Instance, resolveReferenceTypesAsNullable: false, resolveUnderlyingEnumTypes: false); var schemaBuilder = new SchemaBuilder( temporalBehavior: TemporalBehavior.Iso8601, typeResolver: typeResolver); var serializerBuilder = new BinarySerializerBuilder( typeResolver: typeResolver);
After:
var schemaBuilder = new SchemaBuilder( memberVisibility: BindingFlags.Public | BindingFlags.Instance, nullableReferenceTypeBehavior: NullableReferenceTypeBehavior.None, enumBehavior: EnumBehavior.Symbolic, temporalBehavior: TemporalBehavior.Iso8601); var serializerBuilder = new BinarySerializerBuilder( memberVisibility: BindingFlags.Public | BindingFlags.Instance);
As demonstrated above, the
resolveReferenceTypesAsNullable
parameter on the resolver has been replaced by thenullableReferenceTypeBehavior
on the schema builder, which allows for more granular options. In the same vein,resolveUnderlyingEnumTypes
on the resolver has been replaced byenumBehavior
on the schema builder. -
The schema builder now uses nullable reference type annotations to infer whether nullable schemas should be generated. In previous releases, reference type handing was all-or-nothing.
Before:
var typeResolver = new ReflectionResolver( resolveReferenceTypesAsNullable: false); // 😞 var schemaBuilder = new SchemaBuilder( typeResolver: typeResolver);
After:
var schemaBuilder = new SchemaBuilder( nullableReferenceTypeBehavior: NullableReferenceTypeBehavior.Annotated); // 🤠
Annotated
becomes the default behavior in this release, so this is a breaking change. Applications may still useNone
orAll
to keep the behavior of previous versions.--nullable-references
options on the CLI have been updated to match:# Create a schema from a type with nullable reference type analysis enabled (the default behavior): dotnet avro create --assembly bin/Debug/netstandard2.0/Example.dll --type Example.Type --nullable-references annotated # Generate a C# class with nullable reference type annotations enabled (not the default behavior): dotnet avro generate --registry-url http://registry.example --subject example-topic-value --nullable-references
-
An enum schema may be mapped to
string
(#161). Deserialization will always succeed; serialization will throw if the provided value does not exactly match a symbol on the schema. Similarly,Enum
types may now be mapped to a"string"
schema (#188). Serialization will always succeed; deserialization will throw if the serialized value does not exactly match an enumerator.With these changes, the
--enums-as-ints
option on the CLI has been replaced with--enum-behavior
:# Create an "enum" schema (the default behavior): dotnet avro create --type System.DateTimeKind --enum-behavior symbolic # Create an "int" or "long" schema (the behavior for flag enums): dotnet avro create --type System.DateTimeKind --enum-behavior integral # Create a "string" schema (new): dotnet avro create --type System.DateTimeKind --enum-behavior nominal
-
Chr.Avro.Confluent now correctly implements the entirety of the Confluent wire format (#6). Previously, the serdes did not provide any special handling for top-level
"bytes"
schemas even though the wire format provides that only the data (no length information) should be serialized in that case. As this changes serialization behavior, applications that use"bytes"
as a Kafka key or value schema should be upgraded carefully. -
Binary serializers will now throw if a value provided for an
"int"
schema overflows a 32-bit signed integer (#120). Previously, 64-bit signed integers could be written. -
The
IBinaryCodec
abstraction has been replaced by newBinaryReader
andBinaryWriter
objects that complement the System.Text.Json reader/writer:Before:
var codec = new BinaryCodec(); var input = Expression.Parameter(typeof(Stream)); var readInteger = Expression .Lambda<Func<Stream, long>>(codec.ReadInteger(input), new[] { input }) .Compile(); var result = readInteger(stream);
After:
var reader = new BinaryReader(stream); var result = reader.ReadInteger();
Most applications should be unaffected by this change.
New features
-
JSON encoding has been implemented (#2).
-
Default record field values are now supported (#7), enabling classes/structs to be serialized as records even if fields with defaults have no matching member.
-
Mapping
IntPtr
andUIntPtr
to"int"
and"long"
schemas is now supported to enable serializingnint
andnuint
(#140). -
All concrete collection types from System.Collections.ObjectModel are now supported (#97, #189).
Bug fixes
- The schema builder will no longer fail to generate schemas for generic types (#128, #187). Previously, the backtick in a generic type name would cause an invalid record name to be generated.
With this release, we’ve enabled Source Link to improve the debugging experience. We’ve also aligned the codebase to the latest StyleCop analysis rules and C#/.NET versions to make it easier to contribute.