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

NotSupportedException when Deserializing object that has default values for constructor parameters #30854

Closed
EdiWang opened this issue Sep 14, 2019 · 4 comments
Labels
area-System.Text.Json enhancement Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@EdiWang
Copy link

EdiWang commented Sep 14, 2019

The following code throws exception.

static void Main(string[] args)
{
    var obj = new Response(true, "Hi") { ResponseCode = 100 };
    var json = System.Text.Json.JsonSerializer.Serialize(obj);

    // System.NotSupportedException: 'Deserialization of reference types without parameterless constructor is not supported.
    var response = System.Text.Json.JsonSerializer.Deserialize<Response>(json);

    Console.WriteLine(response.Message);
}

public class Response
{
    public bool IsSuccess { get; set; }

    public string Message { get; set; }

    public int ResponseCode { get; set; }

    public Response(bool isSuccess = false, string message = "")
    {
        IsSuccess = isSuccess;
        Message = message;
    }
}

Response class is considered not having a parameterless constructor, but actually it does use default values for parameters, that can be used just like a parameterless constructor, like this:

var test = new Response();

Could the new JSON API check if the constructor parameters have default values before consider it not paremeterless?

Related Issues:
https://github.com/dotnet/corefx/issues/37537

PR:
dotnet/corefx#38061

@ahsonkhan
Copy link
Member

ahsonkhan commented Sep 17, 2019

This is a known limitation of the built-in serializer and requires a feature to support custom ctors. The fact that the custom ctor has default parameters and semantically can be thought of as being parameter-less doesn't affect the serializer logic (which only looks at the ctor that takes 0 arguments).

cc @steveharter

@steveharter
Copy link
Member

cc @layomia PTAL along with similar support for probing for collection ctors (typically immutable)

@layomia
Copy link
Contributor

layomia commented Nov 23, 2019

Closing as duplicate of https://github.com/dotnet/corefx/issues/38569 which considers parameterless/custom constructor support.

We shouldn't do any unguided probing here - the constructor to use should be explicitly marked with an attribute.

@layomia layomia closed this as completed Nov 23, 2019
@sanzor
Copy link

sanzor commented Dec 3, 2019

Hello i have the same error message , and i can't deserialize even if i put a parameterless constructor !

public abstract class MessageClass {
        public enum MessageType {
            Player_Action=0,
        }
        [JsonPropertyName("type")]
        public abstract MessageType Type { get; }
        public MessageClass() {

        }
    }
public class PlayerAction : MessageClass {


        [JsonPropertyName("eventId")]
        public long EventId { get; set; }
        [JsonPropertyName("playerId")]
        public long PlayerId { get; set; }
        public PlayerAction() {

        }
        public override MessageType Type => MessageType.Player_Action;
    }

The error trace is the following;

System.NotSupportedException: Deserialization of reference types without parameterless constructor is not supported. Type 'LS.Models.MessageClass'
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_DeserializeMissingParameterlessConstructor(Type invalidType)
at System.Text.Json.JsonSerializer.HandleStartObject(JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 5.0 milestone Feb 1, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json enhancement Product code improvement that does NOT require public API changes/additions
Projects
None yet
Development

No branches or pull requests

6 participants