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

Could not bind to enums when using Newtonsoft.Json #2289

Closed
Zoe1808 opened this issue Feb 18, 2024 · 6 comments
Closed

Could not bind to enums when using Newtonsoft.Json #2289

Zoe1808 opened this issue Feb 18, 2024 · 6 comments

Comments

@Zoe1808
Copy link

Zoe1808 commented Feb 18, 2024

Description

We've set the serializer to newtonsoft.Json, and got below exceptions when binding to an enum:

[Function("Echo")]
public async Task<HttpResponseData> SampleFunction(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "echo/{type}")]
    HttpRequestData req,
    TypeEnum type)
Exception: Microsoft.Azure.Functions.Worker.FunctionInputConverterException: Error converting 1 input parameters for Function 'Echo': Cannot convert input parameter 'type' to type 'xxx.TypeEnum' from type 'System.String'. Error:Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: T. Path '', line 0, position 0.
[2024-02-18T08:57:50.775Z]    at Newtonsoft.Json.JsonTextReader.ParseValue()
[2024-02-18T08:57:50.777Z]    at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
[2024-02-18T08:57:50.779Z]    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
[2024-02-18T08:57:50.780Z]    at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
[2024-02-18T08:57:50.782Z]    at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
[2024-02-18T08:57:50.788Z]    at Newtonsoft.Json.JsonSerializer.Deserialize(TextReader reader, Type objectType)
[2024-02-18T08:57:50.790Z]    at Azure.Core.Serialization.NewtonsoftJsonObjectSerializer.Deserialize(Stream stream, Type returnType, CancellationToken cancellationToken)
[2024-02-18T08:57:50.792Z]    at Azure.Core.Serialization.NewtonsoftJsonObjectSerializer.DeserializeAsync(Stream stream, Type returnType, CancellationToken cancellationToken)
[2024-02-18T08:57:50.795Z]    at Microsoft.Azure.Functions.Worker.Converters.JsonPocoConverter.GetConversionResultFromDeserialization(Byte[] bytes, Type type) in D:\a\_work\1\s\src\DotNetWorker.Core\Converters\JsonPocoConverter.cs:line 66
[2024-02-18T08:57:50.797Z]    at Microsoft.Azure.Functions.Worker.Context.Features.DefaultFunctionInputBindingFeature.BindFunctionInputAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Context\Features\DefaultFunctionInputBindingFeature.cs:line 94

For TypeEnum, I've added a json converter.

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

[JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))]
public enum TypeEnum
{
    TypeA,
    TypeB
}

Steps to reproduce

see description.

@liliankasem
Copy link
Member

@Zoe1808 can you share how you're configuring the serializer? Sharing the program.cs file should help

@Zoe1808
Copy link
Author

Zoe1808 commented Apr 25, 2024

Hi @liliankasem
We just call this extension method to configure the serializer.

internal static IFunctionsWorkerApplicationBuilder UseNewtonsoftJson(this IFunctionsWorkerApplicationBuilder builder)
{
    builder.Services.Configure<WorkerOptions>(workerOptions =>
    {
        var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
        settings.NullValueHandling = NullValueHandling.Ignore;

        workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
    });

    return builder;
}

We also tried to add the converter, but did not work.

settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

@liliankasem
Copy link
Member

it looks like we don't have an Enum converter so I do not expect this to work. As for using Newtonsoft/System.Text - I don't think they support plain Enum deserialization, it would need to be part of a POCO. I.e.

public class Item
{
    EnumType Type { get; set; }
}

If you do want it to work exactly with an Enum binding, you could write your own converter and register it. We don't have any official docs for that but this blog post outlines the steps for this:

@liliankasem liliankasem added Needs: Author Feedback and removed bug Something isn't working labels Apr 25, 2024
@kshyju
Copy link
Member

kshyju commented Apr 25, 2024

Here is a sample app with a custom converter implementation which binds to the enum.

https://github.com/kshyju/MoreDotnetIsolatedSamples/tree/master/EnumInputConverter

Copy link
Contributor

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.

If you are not the original author (Zoe1808) and believe this issue is not stale, please comment with /bot not-stale and I will not close it.

Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants