Skip to content
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

Unknown type for deserialization when trying to get enum collection in C# #278

Closed
alexvab opened this issue Apr 5, 2024 · 13 comments · Fixed by #291
Closed

Unknown type for deserialization when trying to get enum collection in C# #278

alexvab opened this issue Apr 5, 2024 · 13 comments · Fixed by #291
Labels
area:serialization Focused on functional modules of the product

Comments

@alexvab
Copy link

alexvab commented Apr 5, 2024

Hello, I have an issue with the api endpoint (controller action) which return collection of C# enum as a json
this is my swagger.json file:

{
  "openapi": "3.0.1",
  "info": {
    "title": "KiotaTestApi.WebApi",
    "version": "1.0"
  },
  "paths": {
    "/api/TestData/just-enums": {
      "get": {
        "tags": [
          "TestData"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/KiotaTestApi.Models.Export.MyTaskStatus"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/KiotaTestApi.Models.Export.MyTaskStatus"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/KiotaTestApi.Models.Export.MyTaskStatus"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "KiotaTestApi.Models.Export.MyTaskStatus": {
        "enum": [
          "Pending",
          "InProgress",
          "Done"
        ],
        "type": "string"
      }
    }
  }
}

Here is my controller action definition

    /// <summary>
    /// Get task statuses
    /// </summary>
    /// <returns></returns>
    [HttpGet("just-enums")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IReadOnlyCollection<MyTaskStatus>>> GetStatuses()

When I'm using Kiota ApiClient that has been generated using this swagger.json file above I get an exception when GetAsync method is executed


System.InvalidOperationException: unknown type for deserialization System.Nullable`1[[KiotaTestApi.ApiClient.Models.MyTaskStatus, KiotaTestApi.ApiClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
   at Microsoft.Kiota.Serialization.Json.JsonParseNode.GetCollectionOfPrimitiveValues[T]()+MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at KiotaTestApi.ApiClient.Api.TestData.JustEnums.JustEnumsRequestBuilder.GetAsync(Action`1 requestConfiguration, CancellationToken cancellationToken) 

It seems like enum was handled as a primitive type in GetCollectionOfPrimitiveValues but there is no option for enum there:

...
if(genericType == TypeConstants.BooleanType)
                        yield return (T)(object)currentParseNode.GetBoolValue()!;
                    else if(genericType == TypeConstants.ByteType)
                        yield return (T)(object)currentParseNode.GetByteValue()!;
                    else if(genericType == TypeConstants.SbyteType)
                        yield return (T)(object)currentParseNode.GetSbyteValue()!;
                    else if(genericType == TypeConstants.StringType)
                        yield return (T)(object)currentParseNode.GetStringValue()!;
                    else if(genericType == TypeConstants.IntType)
                        yield return (T)(object)currentParseNode.GetIntValue()!;
                    else if(genericType == TypeConstants.FloatType)
                        yield return (T)(object)currentParseNode.GetFloatValue()!;
                    else if(genericType == TypeConstants.LongType)
                        yield return (T)(object)currentParseNode.GetLongValue()!;
                    else if(genericType == TypeConstants.DoubleType)
                        yield return (T)(object)currentParseNode.GetDoubleValue()!;
                    else if(genericType == TypeConstants.GuidType)
                        yield return (T)(object)currentParseNode.GetGuidValue()!;
                    else if(genericType == TypeConstants.DateTimeOffsetType)
                        yield return (T)(object)currentParseNode.GetDateTimeOffsetValue()!;
                    else if(genericType == TypeConstants.TimeSpanType)
                        yield return (T)(object)currentParseNode.GetTimeSpanValue()!;
                    else if(genericType == TypeConstants.DateType)
                        yield return (T)(object)currentParseNode.GetDateValue()!;
                    else if(genericType == TypeConstants.TimeType)
                        yield return (T)(object)currentParseNode.GetTimeValue()!;
                    else
                        throw new InvalidOperationException($"unknown type for deserialization {genericType.FullName}");

.....

This is my GetAsync method:

 public async Task<List<MyTaskStatus?>?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
        {
#nullable restore
#else
        public async Task<List<MyTaskStatus?>> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
        {
#endif
            var requestInfo = ToGetRequestInformation(requestConfiguration);
            var collectionResult = await RequestAdapter.SendPrimitiveCollectionAsync<MyTaskStatus?>(requestInfo, default, cancellationToken).ConfigureAwait(false);
            return collectionResult?.ToList();
        }

So I'm wondering is this a know issue, or it is something that not supported by Kiota? (I was using versions 1.12 and 1.13)

Please let me know if you need more information.

Thanks!

@andrueastman andrueastman transferred this issue from microsoft/kiota Apr 8, 2024
@andrueastman
Copy link
Member

Transferring this to the json serialization library repository.

@andrueastman
Copy link
Member

Thanks for raising this @alexvab

This is related to #199 and the function you pointed out should ideally be handling enum collections in the meantime until the time a breaking change is made to allow for this scenario to align with other languages.

Any chance you'd be willing to submit a PR to fix this?

@alexvab
Copy link
Author

alexvab commented Apr 14, 2024

Hi @andrueastman Thanks. I could try to submit PR but not sure when I'd be able to make. It looks like I can use Java implementation as a reference for this?

@baywet
Copy link
Member

baywet commented Apr 17, 2024

@andrueastman I think we could get around to that without introducing a breaking change by adding an early case here to check whether the generic type parameter is an enum, and route the call to the GetCollectionOfEnumValues instead.
@alexvab is this something you'd like to explore and submit a pull request for?

@alexvab
Copy link
Author

alexvab commented Apr 18, 2024

@baywet yes I'd like to explore it and submit PR. but not sure how much time I'll have on hand and when I'll be able to submit PR.

@baywet
Copy link
Member

baywet commented Apr 19, 2024

great, let's circle back in a week.

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@baywet
Copy link
Member

baywet commented Apr 29, 2024

@alexvab is this something you started looking at?

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@andrueastman
Copy link
Member

Ping @alexvab

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@andrueastman
Copy link
Member

Transferring issue as part of #238

@andrueastman andrueastman transferred this issue from microsoft/kiota-serialization-json-dotnet Jul 9, 2024
@andrueastman andrueastman added the area:serialization Focused on functional modules of the product label Jul 9, 2024
@andrueastman
Copy link
Member

Resolved with #291

@github-project-automation github-project-automation bot moved this from Todo 📃 to Done ✔️ in Kiota Jul 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:serialization Focused on functional modules of the product
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants