diff --git a/examples/JsonWithReferences/JsonWithReferences.csproj b/examples/JsonWithReferences/JsonWithReferences.csproj index 5d791b989..67124130a 100644 --- a/examples/JsonWithReferences/JsonWithReferences.csproj +++ b/examples/JsonWithReferences/JsonWithReferences.csproj @@ -4,7 +4,7 @@ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} JsonWithReferences Exe - net6.0 + net8.0 7.1 diff --git a/examples/JsonWithReferences/Program.cs b/examples/JsonWithReferences/Program.cs index 1578aec39..765cec217 100644 --- a/examples/JsonWithReferences/Program.cs +++ b/examples/JsonWithReferences/Program.cs @@ -22,9 +22,9 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using NJsonSchema.Generation; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; +using NJsonSchema.NewtonsoftJson.Generation; /// @@ -150,7 +150,7 @@ static async Task Main(string[] args) // from default one to camelCase. // It's also possible to add JsonProperty attributes to customize // serialization mapping and all available NJson attributes. - var jsonSchemaGeneratorSettings = new JsonSchemaGeneratorSettings + var jsonSchemaGeneratorSettings = new NewtonsoftJsonSchemaGeneratorSettings { SerializerSettings = new JsonSerializerSettings { diff --git a/src/Confluent.SchemaRegistry.Serdes.Json/Confluent.SchemaRegistry.Serdes.Json.csproj b/src/Confluent.SchemaRegistry.Serdes.Json/Confluent.SchemaRegistry.Serdes.Json.csproj index cea07e58e..aa265b229 100644 --- a/src/Confluent.SchemaRegistry.Serdes.Json/Confluent.SchemaRegistry.Serdes.Json.csproj +++ b/src/Confluent.SchemaRegistry.Serdes.Json/Confluent.SchemaRegistry.Serdes.Json.csproj @@ -16,14 +16,18 @@ Confluent.SchemaRegistry.Serdes.Json Confluent.SchemaRegistry.Serdes.Json 2.5.2 - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0 true true true Confluent.SchemaRegistry.Serdes.Json.snk - + + + + + diff --git a/src/Confluent.SchemaRegistry.Serdes.Json/JsonDeserializer.cs b/src/Confluent.SchemaRegistry.Serdes.Json/JsonDeserializer.cs index 01a1c50d6..12ba64b35 100644 --- a/src/Confluent.SchemaRegistry.Serdes.Json/JsonDeserializer.cs +++ b/src/Confluent.SchemaRegistry.Serdes.Json/JsonDeserializer.cs @@ -25,7 +25,11 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NJsonSchema; +#if NET8_0_OR_GREATER +using NJsonSchema.NewtonsoftJson.Generation; +#else using NJsonSchema.Generation; +#endif using NJsonSchema.Validation; @@ -53,7 +57,11 @@ namespace Confluent.SchemaRegistry.Serdes /// public class JsonDeserializer : AsyncDeserializer where T : class { +#if NET8_0_OR_GREATER + private readonly NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings; +#else private readonly JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings; +#endif private JsonSchemaValidator validator = new JsonSchemaValidator(); @@ -69,18 +77,30 @@ public class JsonDeserializer : AsyncDeserializer where T : cl /// /// JSON schema generator settings. /// +#if NET8_0_OR_GREATER + public JsonDeserializer(IEnumerable> config = null, NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) : +#else public JsonDeserializer(IEnumerable> config = null, JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) : +#endif this(null, config, jsonSchemaGeneratorSettings) { } - public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, IEnumerable> config = null, JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) +#if NET8_0_OR_GREATER + public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, IEnumerable> config = null, NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) +#else + public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, IEnumerable> config = null, JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) +#endif : this(schemaRegistryClient, config != null ? new JsonDeserializerConfig(config) : null, jsonSchemaGeneratorSettings) { } public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, JsonDeserializerConfig config, +#if NET8_0_OR_GREATER + NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#else JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#endif : base(schemaRegistryClient, config, ruleExecutors) { this.jsonSchemaGeneratorSettings = jsonSchemaGeneratorSettings; @@ -121,7 +141,12 @@ public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, JsonDeserial /// JSON schema generator settings. /// public JsonDeserializer(ISchemaRegistryClient schemaRegistryClient, Schema schema, IEnumerable> config = null, - JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) : this(schemaRegistryClient, config, jsonSchemaGeneratorSettings) +#if NET8_0_OR_GREATER + NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) +#else + JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null) +#endif + : this(schemaRegistryClient, config, jsonSchemaGeneratorSettings) { JsonSchemaResolver utils = new JsonSchemaResolver( schemaRegistryClient, schema, this.jsonSchemaGeneratorSettings); @@ -206,7 +231,11 @@ public override async Task DeserializeAsync(ReadOnlyMemory data, bool i using (var jsonStream = new MemoryStream(array, headerSize, array.Length - headerSize)) using (var jsonReader = new StreamReader(jsonStream, Encoding.UTF8)) { +#if NET8_0_OR_GREATER + JToken json = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonReader.ReadToEnd(), this.jsonSchemaGeneratorSettings?.SerializerSettings); +#else JToken json = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonReader.ReadToEnd(), this.jsonSchemaGeneratorSettings?.ActualSerializerSettings); +#endif json = await ExecuteMigrations(migrations, isKey, subject, topic, context.Headers, json) .ContinueWith(t => (JToken)t.Result) .ConfigureAwait(continueOnCapturedContext: false); @@ -243,7 +272,11 @@ public override async Task DeserializeAsync(ReadOnlyMemory data, bool i } } +#if NET8_0_OR_GREATER + value = Newtonsoft.Json.JsonConvert.DeserializeObject(serializedString, this.jsonSchemaGeneratorSettings?.SerializerSettings); +#else value = Newtonsoft.Json.JsonConvert.DeserializeObject(serializedString, this.jsonSchemaGeneratorSettings?.ActualSerializerSettings); +#endif } } diff --git a/src/Confluent.SchemaRegistry.Serdes.Json/JsonSchemaResolver.cs b/src/Confluent.SchemaRegistry.Serdes.Json/JsonSchemaResolver.cs index 05a500176..e865710d0 100644 --- a/src/Confluent.SchemaRegistry.Serdes.Json/JsonSchemaResolver.cs +++ b/src/Confluent.SchemaRegistry.Serdes.Json/JsonSchemaResolver.cs @@ -20,6 +20,9 @@ using NJsonSchema; using NJsonSchema.Generation; using Newtonsoft.Json.Linq; +#if NET8_0_OR_GREATER +using NJsonSchema.NewtonsoftJson.Generation; +#endif namespace Confluent.SchemaRegistry.Serdes @@ -112,7 +115,11 @@ private async Task GetSchemaUtil(Schema root) { NJsonSchema.Generation.JsonSchemaResolver schemaResolver = new NJsonSchema.Generation.JsonSchemaResolver(rootObject, this.jsonSchemaGeneratorSettings ?? +#if NET8_0_OR_GREATER + new NewtonsoftJsonSchemaGeneratorSettings()); +#else new JsonSchemaGeneratorSettings()); +#endif JsonReferenceResolver referenceResolver = new JsonReferenceResolver(schemaResolver); diff --git a/src/Confluent.SchemaRegistry.Serdes.Json/JsonSerializer.cs b/src/Confluent.SchemaRegistry.Serdes.Json/JsonSerializer.cs index 009e195ea..4a6a4a341 100644 --- a/src/Confluent.SchemaRegistry.Serdes.Json/JsonSerializer.cs +++ b/src/Confluent.SchemaRegistry.Serdes.Json/JsonSerializer.cs @@ -24,9 +24,13 @@ using System.Net; using System.Threading.Tasks; using NJsonSchema; -using NJsonSchema.Generation; using NJsonSchema.Validation; using Confluent.Kafka; +#if NET8_0_OR_GREATER +using NJsonSchema.NewtonsoftJson.Generation; +#else +using NJsonSchema.Generation; +#endif namespace Confluent.SchemaRegistry.Serdes @@ -54,7 +58,11 @@ namespace Confluent.SchemaRegistry.Serdes /// public class JsonSerializer : AsyncSerializer where T : class { +#if NET8_0_OR_GREATER + private readonly NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings; +#else private readonly JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings; +#endif private readonly List ReferenceList = new List(); private JsonSchemaValidator validator = new JsonSchemaValidator(); @@ -82,7 +90,11 @@ public class JsonSerializer : AsyncSerializer where T : class /// JSON schema generator settings. /// public JsonSerializer(ISchemaRegistryClient schemaRegistryClient, JsonSerializerConfig config = null, +#if NET8_0_OR_GREATER + NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#else JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#endif : base(schemaRegistryClient, config, ruleExecutors) { this.jsonSchemaGeneratorSettings = jsonSchemaGeneratorSettings; @@ -136,7 +148,11 @@ public JsonSerializer(ISchemaRegistryClient schemaRegistryClient, JsonSerializer /// JSON schema generator settings. /// public JsonSerializer(ISchemaRegistryClient schemaRegistryClient, Schema schema, JsonSerializerConfig config = null, - JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#if NET8_0_OR_GREATER + NewtonsoftJsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#else + JsonSchemaGeneratorSettings jsonSchemaGeneratorSettings = null, IList ruleExecutors = null) +#endif : this(schemaRegistryClient, config, jsonSchemaGeneratorSettings, ruleExecutors) { foreach (var reference in schema.References) @@ -154,7 +170,7 @@ public JsonSerializer(ISchemaRegistryClient schemaRegistryClient, Schema schema, /// /// Serialize an instance of type to a UTF8 encoded JSON - /// represenation. The serialized data is preceeded by: + /// representation. The serialized data is preceded by: /// 1. A "magic byte" (1 byte) that identifies this as a message with /// Confluent Platform framing. /// 2. The id of the schema as registered in Confluent's Schema Registry @@ -233,7 +249,11 @@ public override async Task SerializeAsync(T value, SerializationContext .ConfigureAwait(continueOnCapturedContext: false); } +#if NET8_0_OR_GREATER + var serializedString = Newtonsoft.Json.JsonConvert.SerializeObject(value, this.jsonSchemaGeneratorSettings?.SerializerSettings); +#else var serializedString = Newtonsoft.Json.JsonConvert.SerializeObject(value, this.jsonSchemaGeneratorSettings?.ActualSerializerSettings); +#endif var validationResult = validator.Validate(serializedString, this.schema); if (validationResult.Count > 0) { diff --git a/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Confluent.SchemaRegistry.Serdes.IntegrationTests.csproj b/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Confluent.SchemaRegistry.Serdes.IntegrationTests.csproj index f1d67147f..2eb779a67 100644 --- a/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Confluent.SchemaRegistry.Serdes.IntegrationTests.csproj +++ b/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Confluent.SchemaRegistry.Serdes.IntegrationTests.csproj @@ -4,7 +4,7 @@ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} UnitTest Confluent.SchemaRegistry.Serdes.IntegrationTests - net6.0 + net8.0 diff --git a/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Tests_Json/UseReferences.cs b/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Tests_Json/UseReferences.cs index fa5047cce..8c940475d 100644 --- a/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Tests_Json/UseReferences.cs +++ b/test/Confluent.SchemaRegistry.Serdes.IntegrationTests/Tests_Json/UseReferences.cs @@ -22,7 +22,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Linq; -using NJsonSchema.Generation; +using NJsonSchema.NewtonsoftJson.Generation; namespace Confluent.SchemaRegistry.Serdes.IntegrationTests @@ -139,7 +139,7 @@ public static void UseReferences(string bootstrapServers, string schemaRegistryS var schemaRegistryConfig = new SchemaRegistryConfig { Url = schemaRegistryServers }; var sr = new CachedSchemaRegistryClient(schemaRegistryConfig); - var jsonSchemaGeneratorSettings = new JsonSchemaGeneratorSettings + var jsonSchemaGeneratorSettings = new NewtonsoftJsonSchemaGeneratorSettings { SerializerSettings = new JsonSerializerSettings { @@ -209,7 +209,7 @@ public static void UseReferences(string bootstrapServers, string schemaRegistryS // Test producing and consuming directly a JObject var serializedString = Newtonsoft.Json.JsonConvert.SerializeObject(order, - jsonSchemaGeneratorSettings.ActualSerializerSettings); + jsonSchemaGeneratorSettings.SerializerSettings); var jsonObject = JObject.Parse(serializedString); using (var producer = diff --git a/test/Confluent.SchemaRegistry.Serdes.UnitTests/Confluent.SchemaRegistry.Serdes.UnitTests.csproj b/test/Confluent.SchemaRegistry.Serdes.UnitTests/Confluent.SchemaRegistry.Serdes.UnitTests.csproj index 1b6e69e32..07284675a 100644 --- a/test/Confluent.SchemaRegistry.Serdes.UnitTests/Confluent.SchemaRegistry.Serdes.UnitTests.csproj +++ b/test/Confluent.SchemaRegistry.Serdes.UnitTests/Confluent.SchemaRegistry.Serdes.UnitTests.csproj @@ -4,7 +4,7 @@ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} UnitTest Confluent.SchemaRegistry.Serdes.UnitTests - net6.0 + net6.0;net8.0 true diff --git a/test/Confluent.SchemaRegistry.Serdes.UnitTests/JsonSerializeDeserialize.cs b/test/Confluent.SchemaRegistry.Serdes.UnitTests/JsonSerializeDeserialize.cs index c5327be09..d9da56830 100644 --- a/test/Confluent.SchemaRegistry.Serdes.UnitTests/JsonSerializeDeserialize.cs +++ b/test/Confluent.SchemaRegistry.Serdes.UnitTests/JsonSerializeDeserialize.cs @@ -21,13 +21,18 @@ using Confluent.SchemaRegistry.Encryption; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -using NJsonSchema.Generation; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; using Xunit; +#if NET8_0_OR_GREATER +using Newtonsoft.Json.Converters; +using NJsonSchema.NewtonsoftJson.Generation; +#else +using NJsonSchema.Generation; +#endif namespace Confluent.SchemaRegistry.Serdes.UnitTests @@ -176,7 +181,11 @@ public async Task WithJsonSerializerSettingsSerDe() { const int value = 1234; var expectedJson = $"{{\"Value\":{value * 2}}}"; +#if NET8_0_OR_GREATER + var jsonSchemaGeneratorSettings = new NewtonsoftJsonSchemaGeneratorSettings +#else var jsonSchemaGeneratorSettings = new JsonSchemaGeneratorSettings +#endif { SerializerSettings = new JsonSerializerSettings { @@ -227,7 +236,11 @@ public async Task WithJsonSchemaExternalReferencesAsync() SubjectNameStrategy = SubjectNameStrategy.TopicRecord }; +#if NET8_0_OR_GREATER + var jsonSchemaGeneratorSettings = new NewtonsoftJsonSchemaGeneratorSettings +#else var jsonSchemaGeneratorSettings = new JsonSchemaGeneratorSettings +#endif { SerializerSettings = new JsonSerializerSettings { @@ -256,6 +269,44 @@ public async Task WithJsonSchemaExternalReferencesAsync() Assert.Equal(v.Field3, actual.Field3); } +#if NET8_0_OR_GREATER + [Theory] + [InlineData("CamelCaseString", EnumType.EnumValue, "{\"Value\":\"enumValue\"}")] + [InlineData("String", EnumType.None, "{\"Value\":\"None\"}")] + [InlineData("Integer", EnumType.OtherValue, "{\"Value\":5678}")] + public async Task WithJsonSchemaGeneratorSettingsSerDe(string enumHandling, EnumType value, + string expectedJson) + { + var serializerSettings = enumHandling switch + { + "CamelCaseString" => new JsonSerializerSettings { Converters = { new StringEnumConverter(new CamelCaseNamingStrategy()) } }, + "String" => new JsonSerializerSettings { Converters = { new StringEnumConverter() } }, + "Integer" => new JsonSerializerSettings(), + _ => throw new ArgumentException("Invalid enumHandling value", nameof(enumHandling)), + }; + + var jsonSchemaGeneratorSettings = new NewtonsoftJsonSchemaGeneratorSettings + { + SerializerSettings = serializerSettings, + }; + + var jsonSerializer = new JsonSerializer(schemaRegistryClient, + jsonSchemaGeneratorSettings: jsonSchemaGeneratorSettings); + var jsonDeserializer = + new JsonDeserializer(jsonSchemaGeneratorSettings: jsonSchemaGeneratorSettings); + + var v = new EnumObject { Value = value }; + var bytes = await jsonSerializer.SerializeAsync(v, + new SerializationContext(MessageComponentType.Value, testTopic)); + Assert.NotNull(bytes); + Assert.Equal(expectedJson, Encoding.UTF8.GetString(bytes.AsSpan().Slice(5))); + + var actual = await jsonDeserializer.DeserializeAsync(bytes, false, + new SerializationContext(MessageComponentType.Value, testTopic)); + Assert.NotNull(actual); + Assert.Equal(actual.Value, value); + } +#else [Theory] [InlineData(EnumHandling.CamelCaseString, EnumType.EnumValue, "{\"Value\":\"enumValue\"}")] [InlineData(EnumHandling.String, EnumType.None, "{\"Value\":\"None\"}")] @@ -284,6 +335,7 @@ public async Task WithJsonSchemaGeneratorSettingsSerDe(EnumHandling enumHandling Assert.NotNull(actual); Assert.Equal(actual.Value, value); } +#endif [Fact] public async Task ValidationFailureReturnsPath()