Skip to content

Commit 18ce801

Browse files
committed
fix: wrong transformation of array items
see #104 Signed-off-by: Pascal Krause <[email protected]>
1 parent c939399 commit 18ce801

File tree

8 files changed

+118
-13
lines changed

8 files changed

+118
-13
lines changed

src/main/java/io/vertx/openapi/validation/transformer/ParameterTransformer.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.vertx.core.json.Json;
2323
import io.vertx.core.json.JsonArray;
2424
import io.vertx.core.json.JsonObject;
25+
import io.vertx.json.schema.common.dsl.SchemaType;
2526
import io.vertx.openapi.contract.Parameter;
2627

2728
public abstract class ParameterTransformer {
@@ -42,7 +43,7 @@ public Object transform(Parameter parameter, String rawValue) {
4243
case ARRAY:
4344
return transformArray(parameter, rawValue);
4445
default:
45-
return transformPrimitive(parameter, rawValue);
46+
return transformPrimitive(parameter.getSchemaType(), rawValue);
4647
}
4748
} catch (DecodeException e) {
4849
throw createCantDecodeValue(parameter);
@@ -52,12 +53,12 @@ public Object transform(Parameter parameter, String rawValue) {
5253
/**
5354
* Like {@link #transform(Parameter, String)}, but only for values considered to be primitive.
5455
*
55-
* @param parameter The parameter model
56+
* @param type The parameter schema type
5657
* @param rawValue The parameter value
5758
* @return An {@link Object} holding the transformed value.
5859
*/
59-
public Object transformPrimitive(Parameter parameter, String rawValue) {
60-
if (STRING.equals(parameter.getSchemaType())) {
60+
public Object transformPrimitive(SchemaType type, String rawValue) {
61+
if (STRING.equals(type)) {
6162
return rawValue;
6263
}
6364

@@ -70,7 +71,7 @@ public Object transformPrimitive(Parameter parameter, String rawValue) {
7071
throw de;
7172
} else {
7273
// let's try it as JSON String
73-
return transformPrimitive(parameter, "\"" + rawValue + "\"");
74+
return transformPrimitive(type, "\"" + rawValue + "\"");
7475
}
7576
}
7677
}
@@ -88,9 +89,11 @@ public Object transformArray(Parameter parameter, String rawValue) {
8889
if (rawValue.isEmpty()) {
8990
return EMPTY_JSON_ARRAY;
9091
}
92+
93+
SchemaType itemsType = getArrayItemSchemaType(parameter);
9194
JsonArray array = new JsonArray();
9295
for (String value : getArrayValues(parameter, rawValue)) {
93-
array.add(transformPrimitive(parameter, value));
96+
array.add(transformPrimitive(itemsType, value));
9497
}
9598
return array;
9699
}
@@ -115,8 +118,18 @@ public Object transformObject(Parameter parameter, String rawValue) {
115118
}
116119
JsonObject object = new JsonObject();
117120
for (int i = 0; i < keysAndValues.length; i = i + 2) {
118-
object.put(keysAndValues[i], transformPrimitive(parameter, keysAndValues[i + 1]));
121+
object.put(keysAndValues[i], transformPrimitive(parameter.getSchemaType(), keysAndValues[i + 1]));
119122
}
120123
return object;
121124
}
125+
126+
// VisibleForTesting
127+
public SchemaType getArrayItemSchemaType(Parameter parameter) {
128+
String itemsType = parameter.getSchema().get("items", new JsonObject()).getString("type");
129+
if (itemsType == null) {
130+
// This allows everything
131+
return SchemaType.OBJECT;
132+
}
133+
return SchemaType.valueOf(itemsType.toUpperCase());
134+
}
122135
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.vertx.tests.test;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
import static io.vertx.core.http.HttpMethod.POST;
5+
import static io.vertx.tests.ResourceHelper.getRelatedTestResourcePath;
6+
import static java.util.stream.Collectors.toList;
7+
8+
import io.vertx.core.Future;
9+
import io.vertx.core.http.HttpClientRequest;
10+
import io.vertx.core.http.HttpClientResponse;
11+
import io.vertx.core.json.JsonArray;
12+
import io.vertx.junit5.Timeout;
13+
import io.vertx.junit5.VertxTestContext;
14+
import io.vertx.openapi.validation.ValidatableResponse;
15+
import io.vertx.openapi.validation.ValidatedRequest;
16+
import io.vertx.tests.test.base.ContractTestBase;
17+
import java.nio.file.Path;
18+
import java.util.List;
19+
import java.util.concurrent.TimeUnit;
20+
import java.util.function.Consumer;
21+
import java.util.function.Function;
22+
import org.junit.jupiter.api.DisplayName;
23+
import org.junit.jupiter.api.Test;
24+
25+
public class ConvertChildItemsCorrectTest extends ContractTestBase {
26+
private Path CONTRACT_FILE = getRelatedTestResourcePath(PhoneNumberTest.class)
27+
.resolve("contract_various_scenarios.yaml");
28+
29+
@Timeout(value = 2, timeUnit = TimeUnit.SECONDS)
30+
@Test
31+
@DisplayName("Test that array items are transformed correctly")
32+
void testArrayItemsShouldBeTransformed(VertxTestContext testContext) {
33+
String operationId = "arrayItems";
34+
String queryParam = "entityId";
35+
List<String> expectedValues = List.of("234534", "123452");
36+
37+
Function<ValidatedRequest, ValidatableResponse> requestProcessor = req -> {
38+
assertThat(req.getQuery().get(queryParam).getJsonArray()).isEqualTo(new JsonArray(expectedValues));
39+
return ValidatableResponse.create(200);
40+
};
41+
42+
Consumer<HttpClientResponse> responseVerifier = resp -> testContext.verify(() -> {
43+
assertThat(resp.statusCode()).isEqualTo(200);
44+
testContext.completeNow();
45+
});
46+
47+
loadContract(CONTRACT_FILE, testContext)
48+
.compose(v -> createServerWithRequestProcessor(requestProcessor, operationId, testContext))
49+
.compose(v -> {
50+
List<String> queryValues = expectedValues.stream().map(s -> queryParam + "=" + s).collect(toList());
51+
String query = String.join("&", queryValues);
52+
Future<HttpClientRequest> req = createRequest(POST, "/arrayItems?" + query, reqOpts -> {});
53+
return sendAndVerifyRequest(req, responseVerifier, testContext);
54+
}).onFailure(testContext::failNow);
55+
}
56+
}

src/test/java/io/vertx/tests/validation/transformer/FormTransformerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private static Stream<Arguments> provideValidObjectValues() {
8787
@ParameterizedTest(name = "{index} Transform \"Cookie\" parameter of style \"from\" with primitive value: {0}")
8888
@MethodSource("provideValidPrimitiveValues")
8989
void testTransformPrimitiveValid(String scenario, Parameter parameter, String rawValue, Object expectedValue) {
90-
assertThat(TRANSFORMER.transformPrimitive(parameter, rawValue)).isEqualTo(expectedValue);
90+
assertThat(TRANSFORMER.transformPrimitive(parameter.getSchemaType(), rawValue)).isEqualTo(expectedValue);
9191
}
9292

9393
@ParameterizedTest(name = "{index} Transform \"Cookie\" parameter of style \"from\" with array value: {0}")

src/test/java/io/vertx/tests/validation/transformer/LabelTransformerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ private static Stream<Arguments> provideValidObjectValues() {
9494
@MethodSource("provideValidPrimitiveValues")
9595
void testTransformPrimitiveValid(String scenario, Parameter parameter, String rawValue, Object expectedValue) {
9696
// Leading dot will be removed in transform method
97-
assertThat(TRANSFORMER.transformPrimitive(parameter, rawValue.substring(1))).isEqualTo(expectedValue);
97+
assertThat(TRANSFORMER.transformPrimitive(parameter.getSchemaType(), rawValue.substring(1)))
98+
.isEqualTo(expectedValue);
9899
}
99100

100101
@ParameterizedTest(name = "{index} Transform \"Path\" parameter of style \"label\" with array value: {0}")

src/test/java/io/vertx/tests/validation/transformer/MatrixTransformerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ private static Stream<Arguments> provideValidObjectValues() {
9292
void testTransformPrimitiveValid(String scenario, Parameter parameter, String rawValue, Object expectedValue) {
9393
// Leading prefix will be removed in transform method
9494
int prefixLength = TRANSFORMER.buildPrefix(parameter).length();
95-
assertThat(TRANSFORMER.transformPrimitive(parameter, rawValue.substring(prefixLength))).isEqualTo(expectedValue);
95+
assertThat(TRANSFORMER.transformPrimitive(parameter.getSchemaType(), rawValue.substring(prefixLength)))
96+
.isEqualTo(expectedValue);
9697
}
9798

9899
@ParameterizedTest(name = "{index} Transform \"Path\" parameter of style \"matrix\" with array value: {0}")

src/test/java/io/vertx/tests/validation/transformer/ParameterTransformerTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.vertx.tests.validation.transformer;
22

33
import static com.google.common.truth.Truth.assertThat;
4+
import static io.vertx.json.schema.common.dsl.SchemaType.STRING;
45
import static io.vertx.json.schema.common.dsl.Schemas.arraySchema;
56
import static io.vertx.json.schema.common.dsl.Schemas.booleanSchema;
67
import static io.vertx.json.schema.common.dsl.Schemas.intSchema;
@@ -18,6 +19,7 @@
1819
import io.vertx.core.json.DecodeException;
1920
import io.vertx.json.schema.JsonSchema;
2021
import io.vertx.json.schema.common.dsl.SchemaBuilder;
22+
import io.vertx.json.schema.common.dsl.SchemaType;
2123
import io.vertx.openapi.contract.Parameter;
2224
import io.vertx.openapi.validation.ValidatorException;
2325
import io.vertx.openapi.validation.transformer.ParameterTransformer;
@@ -50,7 +52,7 @@ public Object transformObject(Parameter parameter, String rawValue) {
5052
}
5153

5254
@Override
53-
public Object transformPrimitive(Parameter parameter, String rawValue) {
55+
public Object transformPrimitive(SchemaType type, String rawValue) {
5456
return "primitive";
5557
}
5658

@@ -84,4 +86,10 @@ void testTransformRouting() {
8486
assertThat(TRANSFORMER.transform(buildSimplePathParameter(arraySchema()), value)).isEqualTo("array");
8587
assertThat(TRANSFORMER.transform(buildSimplePathParameter(objectSchema()), value)).isEqualTo("object");
8688
}
89+
90+
@Test
91+
void testGetArrayItemSchemaType() {
92+
Parameter arrayParam = buildSimplePathParameter(arraySchema().items(stringSchema()));
93+
assertThat(TRANSFORMER.getArrayItemSchemaType(arrayParam)).isEqualTo(STRING);
94+
}
8795
}

src/test/java/io/vertx/tests/validation/transformer/SimpleTransformerTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ private static Stream<Arguments> provideValidObjectValues() {
8888
@ParameterizedTest(name = "{index} Transform \"Path\" parameter of style \"simple\" with primitive value: {0}")
8989
@MethodSource("provideValidPrimitiveValues")
9090
void testTransformPrimitiveValid(String scenario, Parameter parameter, String rawValue, Object expectedValue) {
91-
assertThat(TRANSFORMER.transformPrimitive(parameter, rawValue)).isEqualTo(expectedValue);
91+
assertThat(TRANSFORMER.transformPrimitive(parameter.getSchemaType(), rawValue)).isEqualTo(expectedValue);
9292
}
9393

9494
@ParameterizedTest(name = "{index} Transform \"Path\" parameter of style \"simple\" with array value: {0}")
@@ -105,7 +105,8 @@ void testTransformObjectValid(String scenario, Parameter parameter, String rawVa
105105

106106
@Test
107107
void testInvalidValues() {
108-
assertThrows(DecodeException.class, () -> TRANSFORMER.transformPrimitive(INTEGER_PARAM, "\"no_integer"));
108+
assertThrows(DecodeException.class,
109+
() -> TRANSFORMER.transformPrimitive(INTEGER_PARAM.getSchemaType(), "\"no_integer"));
109110

110111
String invalidObject = "string,foo,number";
111112
ValidatorException exception =

src/test/resources/io/vertx/tests/test/contract_various_scenarios.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,31 @@ paths:
6262
application/json:
6363
schema:
6464
$ref: '#/components/schemas/Error'
65+
/arrayItems:
66+
get:
67+
summary: https://github.com/eclipse-vertx/vertx-openapi/issues/104
68+
operationId: arrayItems
69+
parameters:
70+
- in: query
71+
name: entityId
72+
description: Entity Id
73+
schema:
74+
type: array
75+
items:
76+
type: string
77+
example:
78+
- "234534"
79+
- "123452"
80+
81+
responses:
82+
"200":
83+
description: Doesn't matter
84+
default:
85+
description: unexpected error
86+
content:
87+
application/json:
88+
schema:
89+
$ref: '#/components/schemas/Error'
6590
components:
6691
schemas:
6792
Error:

0 commit comments

Comments
 (0)