This is an automated email from the ASF dual-hosted git repository.

blankensteiner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-dotpulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new b4151ce  Fix Schema.Json<T>() generating empty schema definition (#283)
b4151ce is described below

commit b4151ced65ca6751a911bf748b81d531a35ba285
Author: Thorben Luepkes <[email protected]>
AuthorDate: Mon Mar 2 09:52:31 2026 +0100

    Fix Schema.Json<T>() generating empty schema definition (#283)
    
    Schema.Json<T>() and Schema.Json<T>(options) passed
    Array.Empty<byte>() as SchemaInfo.Data, causing the
    Pulsar broker to reject producers with
    IncompatibleSchemaException ("No content to map due
    to end-of-input").
    
    Add JsonSchemaDefinitionGenerator that auto-generates
    an Avro-style schema definition from T via reflection.
    The parameterless and options-only constructors now use
    the generator. The explicit definition overload is
    unchanged — it remains the escape hatch for custom
    schema strings.
    
    The generator respects JsonPropertyNameAttribute,
    JsonIgnoreAttribute, and PropertyNamingPolicy. It
    handles primitives, nullables, enums, collections,
    dictionaries, and nested record types.
    
    Fixes #282
---
 src/DotPulsar/Schemas/JsonSchema.cs                |  12 +-
 .../Schemas/JsonSchemaDefinitionGenerator.cs       | 193 +++++++++++++++
 .../Schemas/JsonSchemaDefinitionGeneratorTests.cs  | 267 +++++++++++++++++++++
 tests/DotPulsar.Tests/Schemas/JsonSchemaTests.cs   |  45 ++++
 .../Schemas/TestSamples/JsonModels/ComplexModel.cs |  84 +++++++
 5 files changed, 599 insertions(+), 2 deletions(-)

diff --git a/src/DotPulsar/Schemas/JsonSchema.cs 
b/src/DotPulsar/Schemas/JsonSchema.cs
index 45f1411..4147177 100644
--- a/src/DotPulsar/Schemas/JsonSchema.cs
+++ b/src/DotPulsar/Schemas/JsonSchema.cs
@@ -31,13 +31,15 @@ public sealed class JsonSchema<T> : ISchema<T>
     public JsonSchema()
     {
         _options = new JsonSerializerOptions();
-        SchemaInfo = new SchemaInfo(typeof(T).Name, Array.Empty<byte>(), 
SchemaType.Json, ImmutableDictionary<string, string>.Empty);
+        var schemaData = GenerateSchemaData(_options);
+        SchemaInfo = new SchemaInfo(typeof(T).Name, schemaData, 
SchemaType.Json, ImmutableDictionary<string, string>.Empty);
     }
 
     public JsonSchema(JsonSerializerOptions options)
     {
         _options = options;
-        SchemaInfo = new SchemaInfo(typeof(T).Name, Array.Empty<byte>(), 
SchemaType.Json, ImmutableDictionary<string, string>.Empty);
+        var schemaData = GenerateSchemaData(_options);
+        SchemaInfo = new SchemaInfo(typeof(T).Name, schemaData, 
SchemaType.Json, ImmutableDictionary<string, string>.Empty);
     }
 
     public JsonSchema(JsonSerializerOptions options, string 
jsonSchemaDefinition)
@@ -68,4 +70,10 @@ public sealed class JsonSchema<T> : ISchema<T>
         var bytes = JsonSerializer.SerializeToUtf8Bytes(message, _options);
         return new ReadOnlySequence<byte>(bytes);
     }
+
+    private static byte[] GenerateSchemaData(JsonSerializerOptions options)
+    {
+        var definition = JsonSchemaDefinitionGenerator.Generate<T>(options);
+        return Encoding.UTF8.GetBytes(definition);
+    }
 }
diff --git a/src/DotPulsar/Schemas/JsonSchemaDefinitionGenerator.cs 
b/src/DotPulsar/Schemas/JsonSchemaDefinitionGenerator.cs
new file mode 100644
index 0000000..6e398de
--- /dev/null
+++ b/src/DotPulsar/Schemas/JsonSchemaDefinitionGenerator.cs
@@ -0,0 +1,193 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace DotPulsar.Schemas;
+
+using System.Reflection;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+/// <summary>
+/// Generates Avro-style JSON schema definitions from .NET types.
+/// Used by <see cref="JsonSchema{T}"/> to produce broker-compatible schema 
data.
+/// </summary>
+public static class JsonSchemaDefinitionGenerator
+{
+    /// <summary>
+    /// Generate an Avro-style schema definition for the given type.
+    /// </summary>
+    public static string Generate<T>(JsonSerializerOptions? options = null)
+        => Generate(typeof(T), options);
+
+    /// <summary>
+    /// Generate an Avro-style schema definition for the given type.
+    /// </summary>
+    public static string Generate(Type type, JsonSerializerOptions? options = 
null)
+    {
+        var namingPolicy = options?.PropertyNamingPolicy;
+        var sb = new StringBuilder();
+        GenerateRecord(type, namingPolicy, sb);
+        return sb.ToString();
+    }
+
+    private static void GenerateRecord(Type type, JsonNamingPolicy? 
namingPolicy, StringBuilder sb)
+    {
+        sb.Append("{\"type\":\"record\",\"name\":\"");
+        sb.Append(type.Name);
+        sb.Append("\",\"namespace\":\"");
+        sb.Append(type.Namespace ?? string.Empty);
+        sb.Append("\",\"fields\":[");
+
+        var properties = type.GetProperties(BindingFlags.Public | 
BindingFlags.Instance);
+        var first = true;
+
+        foreach (var property in properties)
+        {
+            if (property.GetCustomAttribute<JsonIgnoreAttribute>() is not null)
+                continue;
+
+            if (!first)
+                sb.Append(',');
+
+            first = false;
+
+            var fieldName = ResolveFieldName(property, namingPolicy);
+            var avroType = MapToAvroType(property.PropertyType, namingPolicy, 
sb, fieldNameOnly: true);
+
+            sb.Append("{\"name\":\"");
+            sb.Append(fieldName);
+            sb.Append("\",\"type\":");
+            sb.Append(avroType);
+            sb.Append('}');
+        }
+
+        sb.Append("]}");
+    }
+
+    private static string ResolveFieldName(PropertyInfo property, 
JsonNamingPolicy? namingPolicy)
+    {
+        var jsonPropertyName = 
property.GetCustomAttribute<JsonPropertyNameAttribute>();
+        if (jsonPropertyName is not null)
+            return jsonPropertyName.Name;
+
+        return namingPolicy?.ConvertName(property.Name) ?? property.Name;
+    }
+
+    private static string MapToAvroType(Type type, JsonNamingPolicy? 
namingPolicy, StringBuilder sb, bool fieldNameOnly)
+    {
+        var underlyingType = Nullable.GetUnderlyingType(type);
+        if (underlyingType is not null)
+        {
+            var innerAvro = MapToAvroType(underlyingType, namingPolicy, sb, 
fieldNameOnly);
+            return "[\"null\"," + innerAvro + "]";
+        }
+
+        if (type == typeof(string))
+            return "\"string\"";
+
+        if (type == typeof(int))
+            return "\"int\"";
+
+        if (type == typeof(long))
+            return "\"long\"";
+
+        if (type == typeof(float))
+            return "\"float\"";
+
+        if (type == typeof(double))
+            return "\"double\"";
+
+        if (type == typeof(bool))
+            return "\"boolean\"";
+
+        if (type == typeof(byte[]))
+            return "\"bytes\"";
+
+        if (type == typeof(decimal))
+            return "\"double\"";
+
+        if (type == typeof(short))
+            return "\"int\"";
+
+        if (type == typeof(byte))
+            return "\"int\"";
+
+        if (type == typeof(DateTime) || type == typeof(DateTimeOffset))
+            return "\"string\"";
+
+        if (type == typeof(Guid))
+            return "\"string\"";
+
+        if (type.IsEnum)
+        {
+            var names = Enum.GetNames(type);
+            var enumSb = new StringBuilder();
+            enumSb.Append("{\"type\":\"enum\",\"name\":\"");
+            enumSb.Append(type.Name);
+            enumSb.Append("\",\"symbols\":[");
+            for (var i = 0; i < names.Length; i++)
+            {
+                if (i > 0)
+                    enumSb.Append(',');
+                enumSb.Append('"');
+                enumSb.Append(names[i]);
+                enumSb.Append('"');
+            }
+            enumSb.Append("]}");
+            return enumSb.ToString();
+        }
+
+        if (type.IsArray)
+        {
+            var elementType = type.GetElementType()!;
+            var itemType = MapToAvroType(elementType, namingPolicy, sb, 
fieldNameOnly);
+            return "{\"type\":\"array\",\"items\":" + itemType + "}";
+        }
+
+        if (type.IsGenericType)
+        {
+            var genericDef = type.GetGenericTypeDefinition();
+
+            if (genericDef == typeof(List<>) ||
+                genericDef == typeof(IList<>) ||
+                genericDef == typeof(IEnumerable<>) ||
+                genericDef == typeof(ICollection<>) ||
+                genericDef == typeof(IReadOnlyList<>) ||
+                genericDef == typeof(IReadOnlyCollection<>))
+            {
+                var itemType = MapToAvroType(type.GetGenericArguments()[0], 
namingPolicy, sb, fieldNameOnly);
+                return "{\"type\":\"array\",\"items\":" + itemType + "}";
+            }
+
+            if (genericDef == typeof(Dictionary<,>) ||
+                genericDef == typeof(IDictionary<,>) ||
+                genericDef == typeof(IReadOnlyDictionary<,>))
+            {
+                var valueType = MapToAvroType(type.GetGenericArguments()[1], 
namingPolicy, sb, fieldNameOnly);
+                return "{\"type\":\"map\",\"values\":" + valueType + "}";
+            }
+        }
+
+        // Nested record type — generate inline
+        if (type.IsClass || type.IsValueType && !type.IsPrimitive)
+        {
+            var nestedSb = new StringBuilder();
+            GenerateRecord(type, namingPolicy, nestedSb);
+            return nestedSb.ToString();
+        }
+
+        return "\"string\"";
+    }
+}
diff --git 
a/tests/DotPulsar.Tests/Schemas/JsonSchemaDefinitionGeneratorTests.cs 
b/tests/DotPulsar.Tests/Schemas/JsonSchemaDefinitionGeneratorTests.cs
new file mode 100644
index 0000000..3e94a08
--- /dev/null
+++ b/tests/DotPulsar.Tests/Schemas/JsonSchemaDefinitionGeneratorTests.cs
@@ -0,0 +1,267 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace DotPulsar.Tests.Schemas;
+
+using DotPulsar.Schemas;
+using DotPulsar.Tests.Schemas.TestSamples.JsonModels;
+using System.Text.Json;
+
+[Trait("Category", "Unit")]
+public sealed class JsonSchemaDefinitionGeneratorTests
+{
+    [Fact]
+    public void Generate_GivenSimpleType_ShouldProduceValidAvroSchema()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<PersonModel>();
+
+        //Assert
+        schema.ShouldContain("\"type\":\"record\"");
+        schema.ShouldContain("\"name\":\"PersonModel\"");
+        
schema.ShouldContain("\"namespace\":\"DotPulsar.Tests.Schemas.TestSamples.JsonModels\"");
+        schema.ShouldContain("\"fields\":");
+    }
+
+    [Fact]
+    public void Generate_GivenSimpleType_ShouldIncludeAllPublicProperties()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<PersonModel>();
+
+        //Assert
+        schema.ShouldContain("\"name\":\"Name\"");
+        schema.ShouldContain("\"name\":\"Age\"");
+    }
+
+    [Fact]
+    public void Generate_GivenStringProperty_ShouldMapToAvroString()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<PersonModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var nameField = FindField(fields, "Name");
+
+        //Assert
+        nameField.GetProperty("type").GetString().ShouldBe("string");
+    }
+
+    [Fact]
+    public void Generate_GivenIntProperty_ShouldMapToAvroInt()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<PersonModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var ageField = FindField(fields, "Age");
+
+        //Assert
+        ageField.GetProperty("type").GetString().ShouldBe("int");
+    }
+
+    [Fact]
+    public void Generate_GivenAllPrimitiveTypes_ShouldMapCorrectly()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<AllTypesModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+
+        //Assert
+        FindField(fields, 
"StringField").GetProperty("type").GetString().ShouldBe("string");
+        FindField(fields, 
"IntField").GetProperty("type").GetString().ShouldBe("int");
+        FindField(fields, 
"LongField").GetProperty("type").GetString().ShouldBe("long");
+        FindField(fields, 
"FloatField").GetProperty("type").GetString().ShouldBe("float");
+        FindField(fields, 
"DoubleField").GetProperty("type").GetString().ShouldBe("double");
+        FindField(fields, 
"BoolField").GetProperty("type").GetString().ShouldBe("boolean");
+        FindField(fields, 
"DecimalField").GetProperty("type").GetString().ShouldBe("double");
+    }
+
+    [Fact]
+    public void Generate_GivenNullableProperty_ShouldMapToAvroUnion()
+    {
+        //Act
+        var schema = 
JsonSchemaDefinitionGenerator.Generate<NullableFieldModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var optionalAge = FindField(fields, "OptionalAge");
+
+        //Assert
+        var type = optionalAge.GetProperty("type");
+        type.ValueKind.ShouldBe(JsonValueKind.Array);
+        type[0].GetString().ShouldBe("null");
+        type[1].GetString().ShouldBe("int");
+    }
+
+    [Fact]
+    public void 
Generate_GivenCamelCaseNamingPolicy_ShouldUseCamelCaseFieldNames()
+    {
+        //Arrange
+        var options = new JsonSerializerOptions { PropertyNamingPolicy = 
JsonNamingPolicy.CamelCase };
+
+        //Act
+        var schema = 
JsonSchemaDefinitionGenerator.Generate<PersonModel>(options);
+
+        //Assert — verify field names are camelCase, parse to check precisely
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var fieldNames = new List<string>();
+        foreach (var field in fields.EnumerateArray())
+            fieldNames.Add(field.GetProperty("name").GetString()!);
+
+        fieldNames.ShouldContain("name");
+        fieldNames.ShouldContain("age");
+        fieldNames.ShouldNotContain("Name");
+        fieldNames.ShouldNotContain("Age");
+    }
+
+    [Fact]
+    public void 
Generate_GivenJsonPropertyNameAttribute_ShouldUseAttributeValue()
+    {
+        //Act
+        var schema = 
JsonSchemaDefinitionGenerator.Generate<JsonPropertyNameModel>();
+
+        //Assert
+        schema.ShouldContain("\"name\":\"display_name\"");
+        schema.ShouldContain("\"name\":\"created_at\"");
+        schema.ShouldNotContain("\"name\":\"DisplayName\"");
+    }
+
+    [Fact]
+    public void 
Generate_GivenJsonPropertyNameAttribute_ShouldTakePrecedenceOverNamingPolicy()
+    {
+        //Arrange
+        var options = new JsonSerializerOptions { PropertyNamingPolicy = 
JsonNamingPolicy.CamelCase };
+
+        //Act
+        var schema = 
JsonSchemaDefinitionGenerator.Generate<JsonPropertyNameModel>(options);
+
+        //Assert — attribute wins over naming policy
+        schema.ShouldContain("\"name\":\"display_name\"");
+        schema.ShouldContain("\"name\":\"created_at\"");
+    }
+
+    [Fact]
+    public void Generate_GivenJsonIgnoreAttribute_ShouldExcludeProperty()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<JsonIgnoreModel>();
+
+        //Assert
+        schema.ShouldContain("\"name\":\"Name\"");
+        schema.ShouldNotContain("Secret");
+    }
+
+    [Fact]
+    public void Generate_GivenEnumProperty_ShouldMapToAvroEnum()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<EnumModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var priorityField = FindField(fields, "Priority");
+
+        //Assert
+        var type = priorityField.GetProperty("type");
+        type.GetProperty("type").GetString().ShouldBe("enum");
+        type.GetProperty("name").GetString().ShouldBe("Priority");
+        var symbols = type.GetProperty("symbols");
+        symbols[0].GetString().ShouldBe("Low");
+        symbols[1].GetString().ShouldBe("Medium");
+        symbols[2].GetString().ShouldBe("High");
+    }
+
+    [Fact]
+    public void Generate_GivenNestedType_ShouldGenerateInlineRecord()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<NestedModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var authorField = FindField(fields, "Author");
+
+        //Assert
+        var type = authorField.GetProperty("type");
+        type.GetProperty("type").GetString().ShouldBe("record");
+        type.GetProperty("name").GetString().ShouldBe("PersonModel");
+    }
+
+    [Fact]
+    public void Generate_GivenListProperty_ShouldMapToAvroArray()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<CollectionModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var tagsField = FindField(fields, "Tags");
+
+        //Assert
+        var type = tagsField.GetProperty("type");
+        type.GetProperty("type").GetString().ShouldBe("array");
+        type.GetProperty("items").GetString().ShouldBe("string");
+    }
+
+    [Fact]
+    public void Generate_GivenArrayProperty_ShouldMapToAvroArray()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<CollectionModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var scoresField = FindField(fields, "Scores");
+
+        //Assert
+        var type = scoresField.GetProperty("type");
+        type.GetProperty("type").GetString().ShouldBe("array");
+        type.GetProperty("items").GetString().ShouldBe("int");
+    }
+
+    [Fact]
+    public void Generate_GivenDictionaryProperty_ShouldMapToAvroMap()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<DictionaryModel>();
+        var parsed = JsonDocument.Parse(schema);
+        var fields = parsed.RootElement.GetProperty("fields");
+        var metadataField = FindField(fields, "Metadata");
+
+        //Assert
+        var type = metadataField.GetProperty("type");
+        type.GetProperty("type").GetString().ShouldBe("map");
+        type.GetProperty("values").GetString().ShouldBe("int");
+    }
+
+    [Fact]
+    public void Generate_ShouldProduceValidJson()
+    {
+        //Act
+        var schema = JsonSchemaDefinitionGenerator.Generate<PersonModel>();
+
+        //Assert — should not throw
+        var parsed = JsonDocument.Parse(schema);
+        parsed.RootElement.ValueKind.ShouldBe(JsonValueKind.Object);
+    }
+
+    private static JsonElement FindField(JsonElement fields, string name)
+    {
+        foreach (var field in fields.EnumerateArray())
+        {
+            if (field.GetProperty("name").GetString() == name)
+                return field;
+        }
+
+        throw new InvalidOperationException($"Field '{name}' not found in 
schema fields");
+    }
+}
diff --git a/tests/DotPulsar.Tests/Schemas/JsonSchemaTests.cs 
b/tests/DotPulsar.Tests/Schemas/JsonSchemaTests.cs
index 5e30ee7..fa8b306 100644
--- a/tests/DotPulsar.Tests/Schemas/JsonSchemaTests.cs
+++ b/tests/DotPulsar.Tests/Schemas/JsonSchemaTests.cs
@@ -182,4 +182,49 @@ public sealed class JsonSchemaTests
         //Assert
         
exception.ShouldBeOfType<DotPulsar.Exceptions.SchemaSerializationException>();
     }
+
+    [Fact]
+    public void Constructor_GivenNoArguments_ShouldGenerateNonEmptySchemaData()
+    {
+        //Act
+        var schema = new JsonSchema<PersonModel>();
+
+        //Assert
+        schema.SchemaInfo.Data.Length.ShouldBeGreaterThan(0);
+        var schemaData = 
System.Text.Encoding.UTF8.GetString(schema.SchemaInfo.Data);
+        schemaData.ShouldContain("\"type\":\"record\"");
+        schemaData.ShouldContain("\"name\":\"PersonModel\"");
+    }
+
+    [Fact]
+    public void 
Constructor_GivenCustomOptions_ShouldGenerateNonEmptySchemaData()
+    {
+        //Arrange
+        var options = new JsonSerializerOptions { PropertyNamingPolicy = 
JsonNamingPolicy.CamelCase };
+
+        //Act
+        var schema = new JsonSchema<PersonModel>(options);
+
+        //Assert
+        schema.SchemaInfo.Data.Length.ShouldBeGreaterThan(0);
+        var schemaData = 
System.Text.Encoding.UTF8.GetString(schema.SchemaInfo.Data);
+        schemaData.ShouldContain("\"type\":\"record\"");
+        schemaData.ShouldContain("\"name\":\"name\"");
+        schemaData.ShouldContain("\"name\":\"age\"");
+    }
+
+    [Fact]
+    public void Constructor_GivenExplicitDefinition_ShouldNotAutoGenerate()
+    {
+        //Arrange
+        var customDefinition = "{\"custom\":\"schema\"}";
+        var options = new JsonSerializerOptions();
+
+        //Act
+        var schema = new JsonSchema<PersonModel>(options, customDefinition);
+
+        //Assert — explicit definition should be used as-is
+        var schemaData = 
System.Text.Encoding.UTF8.GetString(schema.SchemaInfo.Data);
+        schemaData.ShouldBe(customDefinition);
+    }
 }
diff --git 
a/tests/DotPulsar.Tests/Schemas/TestSamples/JsonModels/ComplexModel.cs 
b/tests/DotPulsar.Tests/Schemas/TestSamples/JsonModels/ComplexModel.cs
new file mode 100644
index 0000000..c34d645
--- /dev/null
+++ b/tests/DotPulsar.Tests/Schemas/TestSamples/JsonModels/ComplexModel.cs
@@ -0,0 +1,84 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace DotPulsar.Tests.Schemas.TestSamples.JsonModels;
+
+using System.Text.Json.Serialization;
+
+public sealed class NullableFieldModel
+{
+    public string Name { get; set; } = string.Empty;
+    public int? OptionalAge { get; set; }
+    public double? OptionalScore { get; set; }
+}
+
+public sealed class NestedModel
+{
+    public string Title { get; set; } = string.Empty;
+    public PersonModel Author { get; set; } = new();
+}
+
+public sealed class CollectionModel
+{
+    public string Name { get; set; } = string.Empty;
+    public List<string> Tags { get; set; } = [];
+    public int[] Scores { get; set; } = [];
+}
+
+public sealed class JsonPropertyNameModel
+{
+    [JsonPropertyName("display_name")]
+    public string DisplayName { get; set; } = string.Empty;
+
+    [JsonPropertyName("created_at")]
+    public string CreatedAt { get; set; } = string.Empty;
+}
+
+public sealed class JsonIgnoreModel
+{
+    public string Name { get; set; } = string.Empty;
+
+    [JsonIgnore]
+    public string Secret { get; set; } = string.Empty;
+}
+
+public enum Priority
+{
+    Low,
+    Medium,
+    High
+}
+
+public sealed class EnumModel
+{
+    public string Name { get; set; } = string.Empty;
+    public Priority Priority { get; set; }
+}
+
+public sealed class AllTypesModel
+{
+    public string StringField { get; set; } = string.Empty;
+    public int IntField { get; set; }
+    public long LongField { get; set; }
+    public float FloatField { get; set; }
+    public double DoubleField { get; set; }
+    public bool BoolField { get; set; }
+    public decimal DecimalField { get; set; }
+}
+
+public sealed class DictionaryModel
+{
+    public string Name { get; set; } = string.Empty;
+    public Dictionary<string, int> Metadata { get; set; } = new();
+}

Reply via email to