From 47fdd4609b265cb855061def6d5f13498c42433e Mon Sep 17 00:00:00 2001 From: Ulysse Mavrocordatos Date: Fri, 17 Oct 2025 10:33:16 +0200 Subject: [PATCH] Fix oneOf deserialization for parameterized types --- .generator/src/generator/cli.py | 1 + .generator/src/generator/formatter.py | 5 +++++ .generator/src/generator/templates/modelOneOf.j2 | 14 ++++++++++---- .../api/client/v1/model/DistributionPointItem.java | 8 ++++---- .../v1/model/SharedDashboardInvitesData.java | 14 ++++++++++---- .../api/client/v2/model/ActionQuerySpecInputs.java | 9 +++++---- ...reatePipelineEventRequestDataSingleOrArray.java | 14 ++++++++++---- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/.generator/src/generator/cli.py b/.generator/src/generator/cli.py index c5f2cb227bf..6319d5f92e5 100644 --- a/.generator/src/generator/cli.py +++ b/.generator/src/generator/cli.py @@ -52,6 +52,7 @@ def cli(specs, output): env.filters["docstring"] = formatter.docstring env.filters["inline_docstring"] = formatter.inline_docstring env.filters["un_parameterize_type"] = formatter.un_parameterize_type + env.filters["is_parameterized_type"] = formatter.is_parameterized_type env.globals["enumerate"] = enumerate env.globals["get_name"] = openapi.get_name diff --git a/.generator/src/generator/formatter.py b/.generator/src/generator/formatter.py index 34a005c6033..58bbfe7784b 100644 --- a/.generator/src/generator/formatter.py +++ b/.generator/src/generator/formatter.py @@ -157,6 +157,11 @@ def un_parameterize_type(type): return UN_PARAMETERIZE.sub("", type) +def is_parameterized_type(type): + """Check if a type has generic parameters (e.g., List).""" + return '<' in type and '>' in type + + def format_value(value, quotes='"', schema=None, default_value=False, type_=None): if schema: if "enum" in schema and default_value: diff --git a/.generator/src/generator/templates/modelOneOf.j2 b/.generator/src/generator/templates/modelOneOf.j2 index 309bba65674..ee208b14288 100644 --- a/.generator/src/generator/templates/modelOneOf.j2 +++ b/.generator/src/generator/templates/modelOneOf.j2 @@ -70,8 +70,10 @@ public class {{ name }} extends AbstractOpenApiSchema { int match = 0; JsonToken token = tree.traverse(jp.getCodec()).nextToken(); {%- for oneOf in model.oneOf %} - {%- set unParameterizedDataType = get_type(oneOf)|un_parameterize_type %} - // deserialize {{ unParameterizedDataType }} + {%- set parameterizedDataType = get_type(oneOf) %} + {%- set unParameterizedDataType = parameterizedDataType|un_parameterize_type %} + {%- set isParameterized = parameterizedDataType|is_parameterized_type %} + // deserialize {{ parameterizedDataType }} try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper @@ -88,7 +90,11 @@ public class {{ name }} extends AbstractOpenApiSchema { } } if (attemptParsing) { + {%- if isParameterized %} + tmp = tree.traverse(jp.getCodec()).readValueAs(new TypeReference<{{ parameterizedDataType }}>() {}); + {%- else %} tmp = tree.traverse(jp.getCodec()).readValueAs({{ unParameterizedDataType }}.class); + {%- endif %} // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. @@ -101,11 +107,11 @@ public class {{ name }} extends AbstractOpenApiSchema { deserialized = tmp; match++; {% endif %} - log.log(Level.FINER, "Input data matches schema '{{ unParameterizedDataType }}'"); + log.log(Level.FINER, "Input data matches schema '{{ parameterizedDataType }}'"); } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema '{{ unParameterizedDataType }}'", e); + log.log(Level.FINER, "Input data does not match schema '{{ parameterizedDataType }}'", e); } {# #} {%- endfor %} diff --git a/src/main/java/com/datadog/api/client/v1/model/DistributionPointItem.java b/src/main/java/com/datadog/api/client/v1/model/DistributionPointItem.java index bf1a993de93..58ace73a982 100644 --- a/src/main/java/com/datadog/api/client/v1/model/DistributionPointItem.java +++ b/src/main/java/com/datadog/api/client/v1/model/DistributionPointItem.java @@ -121,7 +121,7 @@ public DistributionPointItem deserialize(JsonParser jp, DeserializationContext c log.log(Level.FINER, "Input data does not match schema 'Double'", e); } - // deserialize List + // deserialize List try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper @@ -147,18 +147,18 @@ public DistributionPointItem deserialize(JsonParser jp, DeserializationContext c } } if (attemptParsing) { - tmp = tree.traverse(jp.getCodec()).readValueAs(List.class); + tmp = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. deserialized = tmp; match++; - log.log(Level.FINER, "Input data matches schema 'List'"); + log.log(Level.FINER, "Input data matches schema 'List'"); } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'List'", e); + log.log(Level.FINER, "Input data does not match schema 'List'", e); } DistributionPointItem ret = new DistributionPointItem(); diff --git a/src/main/java/com/datadog/api/client/v1/model/SharedDashboardInvitesData.java b/src/main/java/com/datadog/api/client/v1/model/SharedDashboardInvitesData.java index f5a2ffc8ac8..5dc9e9370eb 100644 --- a/src/main/java/com/datadog/api/client/v1/model/SharedDashboardInvitesData.java +++ b/src/main/java/com/datadog/api/client/v1/model/SharedDashboardInvitesData.java @@ -127,7 +127,7 @@ public SharedDashboardInvitesData deserialize(JsonParser jp, DeserializationCont Level.FINER, "Input data does not match schema 'SharedDashboardInvitesDataObject'", e); } - // deserialize List + // deserialize List try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper @@ -153,18 +153,24 @@ public SharedDashboardInvitesData deserialize(JsonParser jp, DeserializationCont } } if (attemptParsing) { - tmp = tree.traverse(jp.getCodec()).readValueAs(List.class); + tmp = + tree.traverse(jp.getCodec()) + .readValueAs(new TypeReference>() {}); // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. deserialized = tmp; match++; - log.log(Level.FINER, "Input data matches schema 'List'"); + log.log( + Level.FINER, "Input data matches schema 'List'"); } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'List'", e); + log.log( + Level.FINER, + "Input data does not match schema 'List'", + e); } SharedDashboardInvitesData ret = new SharedDashboardInvitesData(); diff --git a/src/main/java/com/datadog/api/client/v2/model/ActionQuerySpecInputs.java b/src/main/java/com/datadog/api/client/v2/model/ActionQuerySpecInputs.java index cd6f2139962..95749950276 100644 --- a/src/main/java/com/datadog/api/client/v2/model/ActionQuerySpecInputs.java +++ b/src/main/java/com/datadog/api/client/v2/model/ActionQuerySpecInputs.java @@ -120,7 +120,7 @@ public ActionQuerySpecInputs deserialize(JsonParser jp, DeserializationContext c log.log(Level.FINER, "Input data does not match schema 'String'", e); } - // deserialize Map + // deserialize Map try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper @@ -146,18 +146,19 @@ public ActionQuerySpecInputs deserialize(JsonParser jp, DeserializationContext c } } if (attemptParsing) { - tmp = tree.traverse(jp.getCodec()).readValueAs(Map.class); + tmp = + tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. deserialized = tmp; match++; - log.log(Level.FINER, "Input data matches schema 'Map'"); + log.log(Level.FINER, "Input data matches schema 'Map'"); } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'Map'", e); + log.log(Level.FINER, "Input data does not match schema 'Map'", e); } ActionQuerySpecInputs ret = new ActionQuerySpecInputs(); diff --git a/src/main/java/com/datadog/api/client/v2/model/CIAppCreatePipelineEventRequestDataSingleOrArray.java b/src/main/java/com/datadog/api/client/v2/model/CIAppCreatePipelineEventRequestDataSingleOrArray.java index c3e7ea042c2..af45d6fa407 100644 --- a/src/main/java/com/datadog/api/client/v2/model/CIAppCreatePipelineEventRequestDataSingleOrArray.java +++ b/src/main/java/com/datadog/api/client/v2/model/CIAppCreatePipelineEventRequestDataSingleOrArray.java @@ -139,7 +139,7 @@ public CIAppCreatePipelineEventRequestDataSingleOrArray deserialize( e); } - // deserialize List + // deserialize List try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper @@ -165,18 +165,24 @@ public CIAppCreatePipelineEventRequestDataSingleOrArray deserialize( } } if (attemptParsing) { - tmp = tree.traverse(jp.getCodec()).readValueAs(List.class); + tmp = + tree.traverse(jp.getCodec()) + .readValueAs(new TypeReference>() {}); // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. deserialized = tmp; match++; - log.log(Level.FINER, "Input data matches schema 'List'"); + log.log( + Level.FINER, "Input data matches schema 'List'"); } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'List'", e); + log.log( + Level.FINER, + "Input data does not match schema 'List'", + e); } CIAppCreatePipelineEventRequestDataSingleOrArray ret =