Azure / autorest.java

Extension for AutoRest (https://github.com/Azure/autorest) that generates Java code
MIT License
33 stars 80 forks source link

tsp, azure-json serialize on generic types #2629

Open weidongxu-microsoft opened 4 months ago

weidongxu-microsoft commented 4 months ago

translate has payload being an array https://github.com/Azure/azure-rest-api-specs/blob/main/specification/translation/Azure.AI.TextTranslation/routes.tsp#L61-L67 (request body and response body is both JSON array)

SDK generates

    @Generated
    @ServiceMethod(returns = ReturnType.SINGLE)
    public List<TransliteratedText> transliterate(String language, String fromScript, String toScript,
        List<InputTextItem> requestBody) {
        // Generated convenience method for transliterateWithResponse
        RequestOptions requestOptions = new RequestOptions();
        return transliterateWithResponse(language, fromScript, toScript, BinaryData.fromObject(requestBody),
            requestOptions).getValue().toObject(TYPE_REFERENCE_LIST_TRANSLITERATED_TEXT);
    }

Serialization within BinaryData would go with Jackson (I assume due to type erasure). It should go with azure-json

Modify the code to

        return transliterateWithResponse(language, fromScript, toScript, BinaryData.fromObject(requestBody.stream().map(BinaryData::fromObject).collect(Collectors.toList())),
            requestOptions).getValue().toObject(TYPE_REFERENCE_LIST_TRANSLITERATED_TEXT);

would work for request body (however it still not desirable in codegen, as the generic type could be e.g. List<Map<List<Map<...>>>). But the response body is hard to work with this pattern.


Kind of similar to https://github.com/Azure/azure-sdk-for-java/issues/37793 (just Jackson vs azure-json, but both having similar problem of type erasure in generic type)

weidongxu-microsoft commented 1 month ago

It still exists on azure-core 1.49.1 https://github.com/Azure/azure-sdk-for-java/pull/40579

[ERROR] com.azure.ai.translation.text.GetLanguagesTests.getSupportedLanguagesTransliterationScopeMultipleScripts -- Time elapsed: 0.520 s <<< ERROR!
java.io.UncheckedIOException: 
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to call `setAccess()` on Constructor 'com.azure.ai.translation.text.models.GetSupportedLanguagesResult' (of class `com.azure.ai.translation.text.models.GetSupportedLanguagesResult`) due to `java.lang.reflect.InaccessibleObjectException`, problem: Unable to make private com.azure.ai.translation.text.models.GetSupportedLanguagesResult() accessible: module com.azure.ai.translation.text does not "opens com.azure.ai.translation.text.models" to module com.fasterxml.jackson.databind
 at [Source: (byte[])"{"transliteration":{"ar":{"name":"Sanitized","nativeName":"العربية","scripts":[{"code":"Arab","name":"Sanitized","nativeName":"العربية","dir":"rtl","toScripts":[{"code":"Latn","name":"Sanitized","nativeName":"اللاتينية","dir":"ltr"}]},{"code":"Latn","name":"Sanitized","nativeName":"اللاتينية","dir":"ltr","toScripts":[{"code":"Arab","name":"Sanitized","nativeName":"العربية","dir":"rtl"}]}]},"as":{"name":"Sanitized","nativeName":"অসমীয়া","scrip"[truncated 16404 bytes]; line: 1, column: 1]
    at com.azure.core.serializer.json.jackson@1.4.13/com.azure.core.serializer.json.jackson.JacksonJsonSerializer.deserializeFromBytes(JacksonJsonSerializer.java:50)
    at com.azure.core@1.49.1/com.azure.core.implementation.util.FluxByteBufferContent.toObject(FluxByteBufferContent.java:99)
    at com.azure.core@1.49.1/com.azure.core.util.BinaryData.toObject(BinaryData.java:1116)
    at com.azure.core@1.49.1/com.azure.core.util.BinaryData.toObject(BinaryData.java:927)
    at com.azure.ai.translation.text@1.1.0-beta.1/com.azure.ai.translation.text.TextTranslationClient.getSupportedLanguages(TextTranslationClient.java:1152)
    at com.azure.ai.translation.text@1.1.0-beta.1/com.azure.ai.translation.text.TextTranslationClient.getSupportedLanguages(TextTranslationClient.java:1180)
    at com.azure.ai.translation.text@1.1.0-beta.1/com.azure.ai.translation.text.GetLanguagesTests.getSupportedLanguagesTransliterationScopeMultipleScripts(GetLanguagesTests.java:65)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
weidongxu-microsoft commented 1 month ago

One hack (if we cannot fix azure-core), is to have codegen generate Alan's helper code https://github.com/Azure/azure-sdk-for-java/pull/40123/commits/bfe05a9a4807e2d90a241a80be8fd6f06e563746

That should handle simple List in response.

A simple List in request may also be handled in codegen (via .stream().map(..).collectToList).

weidongxu-microsoft commented 1 month ago

lib impacted