Skip to content

Commit b653b3e

Browse files
authored
DGS-21988 Fix transformation of nullable JSON props (#2516)
* Fix transformation of nullable JSON props * Minor optimization
1 parent 569917b commit b653b3e

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

src/Confluent.SchemaRegistry.Serdes.Json/JsonUtils.cs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,34 @@ public static async Task<object> Transform(RuleContext ctx, JsonSchema schema, s
4646
{
4747
fieldContext.Type = GetType(schema);
4848
}
49-
49+
50+
if (HasMultipleFlags(schema.Type))
51+
{
52+
JToken jsonObject = JToken.FromObject(message);
53+
foreach (JsonObjectType flag in Enum.GetValues(typeof(JsonObjectType)))
54+
{
55+
if (schema.Type.HasFlag(flag) && !flag.Equals(default(JsonObjectType)))
56+
{
57+
JsonObjectType originalType = schema.Type;
58+
try
59+
{
60+
schema.Type = flag;
61+
var validator = new JsonSchemaValidator();
62+
var errors = validator.Validate(jsonObject, schema);
63+
if (errors.Count == 0)
64+
{
65+
return await Transform(ctx, schema, path, message,
66+
fieldTransform).ConfigureAwait(false);
67+
}
68+
}
69+
finally
70+
{
71+
schema.Type = originalType;
72+
}
73+
}
74+
}
75+
76+
}
5077
if (schema.AllOf.Count > 0 || schema.AnyOf.Count > 0 || schema.OneOf.Count > 0)
5178
{
5279
JToken jsonObject = JToken.FromObject(message);
@@ -139,9 +166,20 @@ public static async Task<object> Transform(RuleContext ctx, JsonSchema schema, s
139166
}
140167
}
141168

169+
private static bool HasMultipleFlags<T>(T flags) where T : Enum
170+
{
171+
var value = Convert.ToInt32(flags);
172+
return value != 0 && (value & (value - 1)) != 0;
173+
}
174+
142175
private static RuleContext.Type GetType(JsonSchema schema)
143176
{
144-
switch (schema.Type)
177+
return GetType(schema.Type);
178+
}
179+
180+
private static RuleContext.Type GetType(JsonObjectType type)
181+
{
182+
switch (type)
145183
{
146184
case JsonObjectType.Object:
147185
return RuleContext.Type.Record;

test/Confluent.SchemaRegistry.Serdes.UnitTests/JsonSerializeDeserialize.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,57 @@ public void CELFieldTransform()
706706
Assert.Equal(user.FavoriteNumber, result.FavoriteNumber);
707707
}
708708

709+
[Fact]
710+
public void CELFieldTransformWithNullable()
711+
{
712+
var schemaStr = @"{
713+
""type"": ""object"",
714+
""properties"": {
715+
""favorite_color"": {
716+
""type"": ""string""
717+
},
718+
""favorite_number"": {
719+
""type"": ""number""
720+
},
721+
""name"": {
722+
""type"": [""string"", ""null""]
723+
}
724+
}
725+
}";
726+
var schema = new RegisteredSchema("topic-value", 1, 1, schemaStr, SchemaType.Json, null);
727+
schema.RuleSet = new RuleSet(new List<Rule>(),
728+
new List<Rule>
729+
{
730+
new Rule("testCEL", RuleKind.Transform, RuleMode.Write, "CEL_FIELD", null, null,
731+
"typeName == 'STRING' ; value + '-suffix'", null, null, false)
732+
}
733+
);
734+
store[schemaStr] = 1;
735+
subjectStore["topic-value"] = new List<RegisteredSchema> { schema };
736+
var config = new JsonSerializerConfig
737+
{
738+
AutoRegisterSchemas = false,
739+
UseLatestVersion = true
740+
};
741+
var serializer = new JsonSerializer<Customer>(schemaRegistryClient, config);
742+
var deserializer = new JsonDeserializer<Customer>(schemaRegistryClient);
743+
744+
var user = new Customer
745+
{
746+
FavoriteColor = "blue",
747+
FavoriteNumber = 100,
748+
Name = "awesome"
749+
};
750+
751+
Headers headers = new Headers();
752+
var bytes = serializer.SerializeAsync(user, new SerializationContext(MessageComponentType.Value, testTopic, headers)).Result;
753+
var result = deserializer.DeserializeAsync(bytes, false, new SerializationContext(MessageComponentType.Value, testTopic, headers)).Result;
754+
755+
Assert.Equal("awesome-suffix", result.Name);
756+
Assert.Equal("blue-suffix", result.FavoriteColor);
757+
Assert.Equal(user.FavoriteNumber, result.FavoriteNumber);
758+
}
759+
709760
[Fact]
710761
public void CELFieldTransformWithDef()
711762
{

0 commit comments

Comments
 (0)