Skip to content

Commit 911009d

Browse files
committed
When parsing oneOf[list-of-models, ...], treat list as unparsed if a model is unparsed.
1 parent 80fbe0b commit 911009d

10 files changed

Lines changed: 151 additions & 12 deletions

File tree

.generator/src/generator/templates/modelOneOf.j2

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ public class {{ name }} extends AbstractOpenApiSchema {
6868
Object tmp = null;
6969
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
7070
int match = 0;
71+
{%- set ns = namespace(has_model_list=false) %}
72+
{%- for oneOf in model.oneOf %}
73+
{%- if "items" in oneOf and oneOf.get("items")|is_model and not oneOf|is_primitive %}
74+
{%- set ns.has_model_list = true %}
75+
{%- endif %}
76+
{%- endfor %}
77+
{%- if ns.has_model_list %}
78+
Object deserializedUnparsed = null;
79+
int matchUnparsed = 0;
80+
{%- endif %}
7181
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
7282
{%- for oneOf in model.oneOf %}
7383
{%- set parameterizedDataType = get_type(oneOf) %}
@@ -103,6 +113,20 @@ public class {{ name }} extends AbstractOpenApiSchema {
103113
deserialized = tmp;
104114
match++;
105115
}
116+
{%- elif "items" in oneOf and oneOf.get("items")|is_model and not oneOf|is_primitive %}
117+
{%- set itemsDataType = get_type(oneOf.get("items")) %}
118+
// keep the matched list, but propagate 'unparsed' from any invalid item
119+
boolean itemsUnparsed = false;
120+
for ({{ itemsDataType }} item : ({{ parameterizedDataType }}) tmp) {
121+
itemsUnparsed |= item.unparsed;
122+
}
123+
if (itemsUnparsed) {
124+
deserializedUnparsed = tmp;
125+
matchUnparsed++;
126+
} else {
127+
deserialized = tmp;
128+
match++;
129+
}
106130
{%- else %}
107131
deserialized = tmp;
108132
match++;
@@ -118,6 +142,11 @@ public class {{ name }} extends AbstractOpenApiSchema {
118142
{{ name }} ret = new {{ name }}();
119143
if (match == 1) {
120144
ret.setActualInstance(deserialized);
145+
{%- if ns.has_model_list %}
146+
} else if (match == 0 && matchUnparsed == 1) {
147+
ret.setActualInstance(deserializedUnparsed);
148+
ret.unparsed = true;
149+
{%- endif %}
121150
} else {
122151
Map<String, Object> res = new ObjectMapper().readValue(tree.traverse(jp.getCodec()).readValueAsTree().toString(), new TypeReference<Map<String, Object>>() {});
123152
ret.setActualInstance(new UnparsedObject(res));

src/main/java/com/datadog/api/client/v1/model/FormulaAndFunctionEventQueryGroupByConfig.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public FormulaAndFunctionEventQueryGroupByConfig deserialize(
9090
Object tmp = null;
9191
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
9292
int match = 0;
93+
Object deserializedUnparsed = null;
94+
int matchUnparsed = 0;
9395
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
9496
// deserialize List<FormulaAndFunctionEventQueryGroupBy>
9597
try {
@@ -123,9 +125,19 @@ public FormulaAndFunctionEventQueryGroupByConfig deserialize(
123125
// TODO: there is no validation against JSON schema constraints
124126
// (min, max, enum, pattern...), this does not perform a strict JSON
125127
// validation, which means the 'match' count may be higher than it should be.
126-
deserialized = tmp;
127-
match++;
128-
128+
// keep the matched list, but propagate 'unparsed' from any invalid item
129+
boolean itemsUnparsed = false;
130+
for (FormulaAndFunctionEventQueryGroupBy item :
131+
(List<FormulaAndFunctionEventQueryGroupBy>) tmp) {
132+
itemsUnparsed |= item.unparsed;
133+
}
134+
if (itemsUnparsed) {
135+
deserializedUnparsed = tmp;
136+
matchUnparsed++;
137+
} else {
138+
deserialized = tmp;
139+
match++;
140+
}
129141
log.log(
130142
Level.FINER, "Input data matches schema 'List<FormulaAndFunctionEventQueryGroupBy>'");
131143
}
@@ -192,6 +204,9 @@ public FormulaAndFunctionEventQueryGroupByConfig deserialize(
192204
new FormulaAndFunctionEventQueryGroupByConfig();
193205
if (match == 1) {
194206
ret.setActualInstance(deserialized);
207+
} else if (match == 0 && matchUnparsed == 1) {
208+
ret.setActualInstance(deserializedUnparsed);
209+
ret.unparsed = true;
195210
} else {
196211
Map<String, Object> res =
197212
new ObjectMapper()

src/main/java/com/datadog/api/client/v1/model/SharedDashboardInvitesData.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ public SharedDashboardInvitesData deserialize(JsonParser jp, DeserializationCont
8080
Object tmp = null;
8181
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
8282
int match = 0;
83+
Object deserializedUnparsed = null;
84+
int matchUnparsed = 0;
8385
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8486
// deserialize SharedDashboardInvitesDataObject
8587
try {
@@ -159,9 +161,19 @@ public SharedDashboardInvitesData deserialize(JsonParser jp, DeserializationCont
159161
// TODO: there is no validation against JSON schema constraints
160162
// (min, max, enum, pattern...), this does not perform a strict JSON
161163
// validation, which means the 'match' count may be higher than it should be.
162-
deserialized = tmp;
163-
match++;
164-
164+
// keep the matched list, but propagate 'unparsed' from any invalid item
165+
boolean itemsUnparsed = false;
166+
for (SharedDashboardInvitesDataObject item :
167+
(List<SharedDashboardInvitesDataObject>) tmp) {
168+
itemsUnparsed |= item.unparsed;
169+
}
170+
if (itemsUnparsed) {
171+
deserializedUnparsed = tmp;
172+
matchUnparsed++;
173+
} else {
174+
deserialized = tmp;
175+
match++;
176+
}
165177
log.log(
166178
Level.FINER, "Input data matches schema 'List<SharedDashboardInvitesDataObject>'");
167179
}
@@ -176,6 +188,9 @@ public SharedDashboardInvitesData deserialize(JsonParser jp, DeserializationCont
176188
SharedDashboardInvitesData ret = new SharedDashboardInvitesData();
177189
if (match == 1) {
178190
ret.setActualInstance(deserialized);
191+
} else if (match == 0 && matchUnparsed == 1) {
192+
ret.setActualInstance(deserializedUnparsed);
193+
ret.unparsed = true;
179194
} else {
180195
Map<String, Object> res =
181196
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/AnyValue.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public AnyValue deserialize(JsonParser jp, DeserializationContext ctxt)
7777
Object tmp = null;
7878
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
7979
int match = 0;
80+
Object deserializedUnparsed = null;
81+
int matchUnparsed = 0;
8082
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8183
// deserialize String
8284
try {
@@ -232,9 +234,18 @@ public AnyValue deserialize(JsonParser jp, DeserializationContext ctxt)
232234
// TODO: there is no validation against JSON schema constraints
233235
// (min, max, enum, pattern...), this does not perform a strict JSON
234236
// validation, which means the 'match' count may be higher than it should be.
235-
deserialized = tmp;
236-
match++;
237-
237+
// keep the matched list, but propagate 'unparsed' from any invalid item
238+
boolean itemsUnparsed = false;
239+
for (AnyValueItem item : (List<AnyValueItem>) tmp) {
240+
itemsUnparsed |= item.unparsed;
241+
}
242+
if (itemsUnparsed) {
243+
deserializedUnparsed = tmp;
244+
matchUnparsed++;
245+
} else {
246+
deserialized = tmp;
247+
match++;
248+
}
238249
log.log(Level.FINER, "Input data matches schema 'List<AnyValueItem>'");
239250
}
240251
} catch (Exception e) {
@@ -286,6 +297,9 @@ public AnyValue deserialize(JsonParser jp, DeserializationContext ctxt)
286297
AnyValue ret = new AnyValue();
287298
if (match == 1) {
288299
ret.setActualInstance(deserialized);
300+
} else if (match == 0 && matchUnparsed == 1) {
301+
ret.setActualInstance(deserializedUnparsed);
302+
ret.unparsed = true;
289303
} else {
290304
Map<String, Object> res =
291305
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/CIAppAggregateBucketValue.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public CIAppAggregateBucketValue deserialize(JsonParser jp, DeserializationConte
7979
Object tmp = null;
8080
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
8181
int match = 0;
82+
Object deserializedUnparsed = null;
83+
int matchUnparsed = 0;
8284
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8385
// deserialize String
8486
try {
@@ -213,6 +215,9 @@ public CIAppAggregateBucketValue deserialize(JsonParser jp, DeserializationConte
213215
CIAppAggregateBucketValue ret = new CIAppAggregateBucketValue();
214216
if (match == 1) {
215217
ret.setActualInstance(deserialized);
218+
} else if (match == 0 && matchUnparsed == 1) {
219+
ret.setActualInstance(deserializedUnparsed);
220+
ret.unparsed = true;
216221
} else {
217222
Map<String, Object> res =
218223
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/CIAppCreatePipelineEventRequestDataSingleOrArray.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public CIAppCreatePipelineEventRequestDataSingleOrArray deserialize(
9090
Object tmp = null;
9191
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
9292
int match = 0;
93+
Object deserializedUnparsed = null;
94+
int matchUnparsed = 0;
9395
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
9496
// deserialize CIAppCreatePipelineEventRequestData
9597
try {
@@ -171,9 +173,19 @@ public CIAppCreatePipelineEventRequestDataSingleOrArray deserialize(
171173
// TODO: there is no validation against JSON schema constraints
172174
// (min, max, enum, pattern...), this does not perform a strict JSON
173175
// validation, which means the 'match' count may be higher than it should be.
174-
deserialized = tmp;
175-
match++;
176-
176+
// keep the matched list, but propagate 'unparsed' from any invalid item
177+
boolean itemsUnparsed = false;
178+
for (CIAppCreatePipelineEventRequestData item :
179+
(List<CIAppCreatePipelineEventRequestData>) tmp) {
180+
itemsUnparsed |= item.unparsed;
181+
}
182+
if (itemsUnparsed) {
183+
deserializedUnparsed = tmp;
184+
matchUnparsed++;
185+
} else {
186+
deserialized = tmp;
187+
match++;
188+
}
177189
log.log(
178190
Level.FINER, "Input data matches schema 'List<CIAppCreatePipelineEventRequestData>'");
179191
}
@@ -189,6 +201,9 @@ public CIAppCreatePipelineEventRequestDataSingleOrArray deserialize(
189201
new CIAppCreatePipelineEventRequestDataSingleOrArray();
190202
if (match == 1) {
191203
ret.setActualInstance(deserialized);
204+
} else if (match == 0 && matchUnparsed == 1) {
205+
ret.setActualInstance(deserializedUnparsed);
206+
ret.unparsed = true;
192207
} else {
193208
Map<String, Object> res =
194209
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/LogsAggregateBucketValue.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public LogsAggregateBucketValue deserialize(JsonParser jp, DeserializationContex
7979
Object tmp = null;
8080
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
8181
int match = 0;
82+
Object deserializedUnparsed = null;
83+
int matchUnparsed = 0;
8284
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8385
// deserialize String
8486
try {
@@ -213,6 +215,9 @@ public LogsAggregateBucketValue deserialize(JsonParser jp, DeserializationContex
213215
LogsAggregateBucketValue ret = new LogsAggregateBucketValue();
214216
if (match == 1) {
215217
ret.setActualInstance(deserialized);
218+
} else if (match == 0 && matchUnparsed == 1) {
219+
ret.setActualInstance(deserializedUnparsed);
220+
ret.unparsed = true;
216221
} else {
217222
Map<String, Object> res =
218223
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/RUMAggregateBucketValue.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public RUMAggregateBucketValue deserialize(JsonParser jp, DeserializationContext
7979
Object tmp = null;
8080
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
8181
int match = 0;
82+
Object deserializedUnparsed = null;
83+
int matchUnparsed = 0;
8284
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8385
// deserialize String
8486
try {
@@ -211,6 +213,9 @@ public RUMAggregateBucketValue deserialize(JsonParser jp, DeserializationContext
211213
RUMAggregateBucketValue ret = new RUMAggregateBucketValue();
212214
if (match == 1) {
213215
ret.setActualInstance(deserialized);
216+
} else if (match == 0 && matchUnparsed == 1) {
217+
ret.setActualInstance(deserializedUnparsed);
218+
ret.unparsed = true;
214219
} else {
215220
Map<String, Object> res =
216221
new ObjectMapper()

src/main/java/com/datadog/api/client/v2/model/SpansAggregateBucketValue.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public SpansAggregateBucketValue deserialize(JsonParser jp, DeserializationConte
7979
Object tmp = null;
8080
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
8181
int match = 0;
82+
Object deserializedUnparsed = null;
83+
int matchUnparsed = 0;
8284
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
8385
// deserialize String
8486
try {
@@ -213,6 +215,9 @@ public SpansAggregateBucketValue deserialize(JsonParser jp, DeserializationConte
213215
SpansAggregateBucketValue ret = new SpansAggregateBucketValue();
214216
if (match == 1) {
215217
ret.setActualInstance(deserialized);
218+
} else if (match == 0 && matchUnparsed == 1) {
219+
ret.setActualInstance(deserializedUnparsed);
220+
ret.unparsed = true;
216221
} else {
217222
Map<String, Object> res =
218223
new ObjectMapper()

src/test/java/com/datadog/api/client/v1/api/DashboardsApiTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,4 +1099,35 @@ public void testUserJourneyFormulaGroupByPropagatesUnparsed() throws Exception {
10991099
invalid.getGroupBy().get(0).unparsed);
11001100
assertTrue("query must propagate unparsed from its group_by items", invalid.unparsed);
11011101
}
1102+
1103+
private static String eventQuery(String sortAggregation) {
1104+
return "{"
1105+
+ "\"data_source\":\"logs\","
1106+
+ "\"name\":\"query1\","
1107+
+ "\"compute\":{\"aggregation\":\"count\"},"
1108+
+ "\"group_by\":[{\"facet\":\"@x\",\"sort\":{\"aggregation\":\""
1109+
+ sortAggregation
1110+
+ "\",\"order\":\"asc\"}}]"
1111+
+ "}";
1112+
}
1113+
1114+
@Test
1115+
public void testEventQueryOneOfGroupByPropagatesUnparsed() throws Exception {
1116+
ObjectMapper mapper = generalApiClient.getJSON().getMapper();
1117+
1118+
// An invalid sort inside the group_by list, which is itself wrapped in a oneOf, must
1119+
// propagate unparsed up to the query.
1120+
FormulaAndFunctionEventQueryDefinition invalid =
1121+
com.datadog.api.World.fromJSON(
1122+
mapper,
1123+
FormulaAndFunctionEventQueryDefinition.class,
1124+
eventQuery("NOT_A_VALID_AGGREGATION"));
1125+
assertTrue(
1126+
"group-by list item must propagate unparsed from its sort",
1127+
invalid.getGroupBy().getList().get(0).unparsed);
1128+
assertTrue(
1129+
"oneOf group_by wrapper must propagate unparsed from its list items",
1130+
invalid.getGroupBy().unparsed);
1131+
assertTrue("query must propagate unparsed from its group_by", invalid.unparsed);
1132+
}
11021133
}

0 commit comments

Comments
 (0)