-
Notifications
You must be signed in to change notification settings - Fork 333
http-client-java, bug fix, array encoding support closed enum #9413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8464593
3ed9b18
8e7b15b
4a82a97
56b3a56
d12f548
6d463e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ | |
| /** | ||
| * The details of a class type that is used by a client. | ||
| */ | ||
| public class ClassType implements IType, ConvertToJsonTypeTrait { | ||
| public class ClassType implements IType, ConvertToJsonTypeTrait, ConvertFromJsonTypeTrait { | ||
| private static ClassType withClientCoreReplacement(String azureClass, String clientCoreClass) { | ||
| return withClientCoreAndVNextReplacement(azureClass, clientCoreClass, clientCoreClass); | ||
| } | ||
|
|
@@ -282,6 +282,7 @@ private static Builder withVNextReplacementBuilder(String azureClass, String azu | |
| public static final ClassType POLLER_FLUX = new ClassType("com.azure.core.util.polling", "PollerFlux"); | ||
|
|
||
| // Complex mapped types | ||
| // JSON type is STRING, wire type is Base64Url/Base64Uri, client type is byte[] | ||
| public static final ClassType BASE_64_URL | ||
| = withClientCoreReplacementBuilder("com.azure.core.util.Base64Url", "io.clientcore.core.utils.Base64Uri", false) | ||
| .serializationValueGetterModifier(valueGetter -> "Objects.toString(" + valueGetter + ", null)") | ||
|
|
@@ -310,6 +311,7 @@ private static Builder withVNextReplacementBuilder(String azureClass, String azu | |
| .xmlAttributeDeserializationTemplate("%s.getNullableAttribute(%s, %s, BinaryData::fromObject)") | ||
| .build(); | ||
|
|
||
| // JSON type is STRING, wire type is DateTimeRfc1123, client type is OffsetDateTime | ||
| public static final ClassType DATE_TIME_RFC_1123 | ||
| = withClientCoreReplacementBuilder("com.azure.core.util.DateTimeRfc1123", | ||
| "io.clientcore.core.utils.DateTimeRfc1123", false) | ||
|
|
@@ -497,8 +499,11 @@ private static Builder withVNextReplacementBuilder(String azureClass, String azu | |
| .xmlAttributeDeserializationTemplate("%s.getNullableAttribute(%s, %s, OffsetDateTime::parse)") | ||
| .build(); | ||
|
|
||
| // JSON type is NUMERIC, client type is OffsetDateTime | ||
| public static final ClassType UNIX_TIME_LONG = new ClassType.Builder(false).prototypeAsLong().build(); | ||
| // JSON type is NUMERIC, client type is Duration | ||
| public static final ClassType DURATION_LONG = new ClassType.Builder(false).prototypeAsLong().build(); | ||
| // JSON type is NUMERIC, client type is Duration | ||
| public static final ClassType DURATION_DOUBLE = new ClassType.Builder(false).prototypeAsDouble().build(); | ||
|
|
||
| public static final ClassType URL = new Builder(false) | ||
|
|
@@ -786,9 +791,31 @@ public boolean isUsedInXml() { | |
|
|
||
| @Override | ||
| public String convertToJsonType(String variableName) { | ||
| String expression = convertFromClientType(variableName); | ||
| return serializationValueGetterModifier != null | ||
| ? serializationValueGetterModifier.apply(variableName) | ||
| : variableName; | ||
| ? serializationValueGetterModifier.apply(expression) | ||
| : expression; | ||
| } | ||
|
|
||
| @Override | ||
| public String convertFromJsonType(String variableName) { | ||
| // TODO (weidxu): it may be better to refactor it to type initialization, similar as | ||
| // defaultValueExpressionConverter | ||
| if (this == ClassType.INTEGER_AS_STRING) { | ||
| return variableName + " == null ? null : Integer.parseInt(" + variableName + ")"; | ||
| } else if (this == ClassType.LONG_AS_STRING) { | ||
| return variableName + " == null ? null : Long.parseInt(" + variableName + ")"; | ||
| } else if (this == ClassType.DATE_TIME) { | ||
| return variableName + " == null ? null : OffsetDateTime.parse(" + variableName + ")"; | ||
| } else if (this == ClassType.DATE_TIME_RFC_1123) { | ||
| return variableName + " == null ? null : new DateTimeRfc1123(" + variableName + ")"; | ||
| } else if (this == ClassType.DURATION) { | ||
| return variableName + " == null ? null : Duration.parse(" + variableName + ")"; | ||
| } else if (this == ClassType.URL) { | ||
| return variableName + " == null ? null : new URL(" + variableName + ")"; | ||
| } else { | ||
| return convertToClientType(variableName); | ||
| } | ||
|
Comment on lines
+802
to
+818
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wonder can we put this into And what's the difference between
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wire type can be e.g.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "wire type" in codegen may not be what you think "on wire". It is more an "internal type" (compared to client type as "customer facing type"). For models, since codegen now own the serialization/de- (no Jackson needed), this "internal type" may not be useful at all. E.g. we should be able to directly convert a JSON string to OffsetDateTime, according to RFC1123/7231 protocol (instead of the usual RFC3339). However, for proxy method, the core / clientcore still takes this "internal type" for request parameter / body / response body. |
||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| package com.microsoft.typespec.http.client.generator.core.model.clientmodel; | ||
|
|
||
| /** | ||
| * Trait for types that can convert a JSON wire value back into the client type. | ||
| */ | ||
| public interface ConvertFromJsonTypeTrait { | ||
|
|
||
| /** | ||
| * Gets the expression that converts the JSON wire value into this type. | ||
| * | ||
| * @param variableName The variable to convert. | ||
| * @return The expression that converts the variable to this type. | ||
| */ | ||
| String convertFromJsonType(String variableName); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| package com.microsoft.typespec.http.client.generator.core.model.clientmodel; | ||
|
|
||
| import java.util.List; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| public class ConvertFromJsonTypeTraitTests { | ||
|
|
||
| @Test | ||
| public void testPrimitiveTypeConversion() { | ||
| Assertions.assertEquals("var", PrimitiveType.INT.convertFromJsonType("var")); | ||
| Assertions.assertEquals("var == null ? null : Integer.parseInt(var)", | ||
| PrimitiveType.INT_AS_STRING.convertFromJsonType("var")); | ||
| Assertions.assertEquals("Duration.ofNanos((long) (var * 1000_000_000L))", | ||
| PrimitiveType.DURATION_DOUBLE.convertFromJsonType("var")); | ||
| Assertions.assertEquals("OffsetDateTime.ofInstant(Instant.ofEpochSecond(var), ZoneOffset.UTC)", | ||
| PrimitiveType.UNIX_TIME_LONG.convertFromJsonType("var")); | ||
| } | ||
|
|
||
| @Test | ||
| public void testClassTypeConversion() { | ||
| Assertions.assertEquals("var", ClassType.LONG.convertFromJsonType("var")); | ||
| Assertions.assertEquals("var == null ? null : new DateTimeRfc1123(var)", | ||
| ClassType.DATE_TIME_RFC_1123.convertFromJsonType("var")); | ||
| Assertions.assertEquals("var == null ? null : OffsetDateTime.parse(var)", | ||
| ClassType.DATE_TIME.convertFromJsonType("var")); | ||
| Assertions.assertEquals("var == null ? null : Duration.parse(var)", | ||
| ClassType.DURATION.convertFromJsonType("var")); | ||
| Assertions.assertEquals("Duration.ofSeconds(var)", ClassType.DURATION_LONG.convertFromJsonType("var")); | ||
| } | ||
weidongxu-microsoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @Test | ||
| public void testEnumConversion() { | ||
| ClientEnumValue enumValue = new ClientEnumValue("VALUE_ONE", "1", "ValueOne"); | ||
|
|
||
| EnumType.Builder enumTypeBuilder = new EnumType.Builder().name("SampleEnum") | ||
| .elementType(ClassType.STRING) | ||
| .values(List.of(enumValue)) | ||
| .expandable(true); | ||
|
|
||
| Assertions.assertEquals("var == null ? null : SampleEnum.fromString(var)", | ||
| enumTypeBuilder.build().convertFromJsonType("var")); | ||
|
|
||
| enumTypeBuilder.expandable(false); | ||
| Assertions.assertEquals("var == null ? null : SampleEnum.fromString(var)", | ||
| enumTypeBuilder.build().convertFromJsonType("var")); | ||
|
|
||
| enumTypeBuilder.elementType(ClassType.INTEGER); | ||
| Assertions.assertEquals("var == null ? null : SampleEnum.fromInteger(var)", | ||
| enumTypeBuilder.build().convertFromJsonType("var")); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| package com.microsoft.typespec.http.client.generator.core.model.clientmodel; | ||
|
|
||
| import java.util.List; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| public class ConvertToJsonTypeTraitTests { | ||
|
|
||
| @Test | ||
| public void testPrimitiveTypeConversion() { | ||
| Assertions.assertEquals("var", PrimitiveType.INT.convertToJsonType("var")); | ||
| Assertions.assertEquals("Objects.toString(var, null)", PrimitiveType.INT_AS_STRING.convertToJsonType("var")); | ||
| Assertions.assertEquals("(double) var.toNanos() / 1000_000_000L", | ||
| PrimitiveType.DURATION_DOUBLE.convertToJsonType("var")); | ||
| } | ||
|
|
||
| @Test | ||
| public void testClassTypeConversion() { | ||
| Assertions.assertEquals("var", ClassType.LONG.convertToJsonType("var")); | ||
| Assertions.assertEquals("Objects.toString(new DateTimeRfc1123(var), null)", | ||
| ClassType.DATE_TIME_RFC_1123.convertToJsonType("var")); | ||
| Assertions.assertEquals("var == null ? null : DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(var)", | ||
| ClassType.DATE_TIME.convertToJsonType("var")); | ||
| Assertions.assertEquals("CoreUtils.durationToStringWithDays(var)", ClassType.DURATION.convertToJsonType("var")); | ||
| } | ||
weidongxu-microsoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @Test | ||
| public void testEnumConversion() { | ||
| ClientEnumValue enumValue = new ClientEnumValue("VALUE_ONE", "ValueOne", "ValueOne"); | ||
|
|
||
| EnumType.Builder enumTypeBuilder = new EnumType.Builder().name("SampleEnum") | ||
| .elementType(ClassType.STRING) | ||
| .values(List.of(enumValue)) | ||
| .expandable(true); | ||
|
|
||
| Assertions.assertEquals("var == null ? null : var.toString()", | ||
| enumTypeBuilder.build().convertToJsonType("var")); | ||
|
|
||
| enumTypeBuilder.expandable(false); | ||
| Assertions.assertEquals("var == null ? null : var.toString()", | ||
| enumTypeBuilder.build().convertToJsonType("var")); | ||
|
|
||
| enumTypeBuilder.elementType(ClassType.INTEGER); | ||
| Assertions.assertEquals("var == null ? null : var.toInteger()", | ||
| enumTypeBuilder.build().convertToJsonType("var")); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.