NotSupportedException: Deserialization of types without a parameterless constructor, a
singular parameterized constructor, or a parameterized constructor annotated with
'JsonConstructorAttribute' is not supported means System.Text.Json found a class it
could not decide how to create. The message lists the three shapes it accepts. In the case
reproduced here the class had two constructors with parameters and no empty one, and
marking one of them with [JsonConstructor] fixed it.
Pick the constructor whose parameters match the JSON properties, put
[JsonConstructor] on it, and the same JSON deserializes with both values
filled.
The error
Unhandled exception. System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'Contact'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'Contact'.
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack& state, Utf8JsonReader& reader, Exception innerException)
...
at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
at Program.<Main>$(String[] args) in C:\...\pc\Program.cs:line 13
Why it happens
The class that failed had read-only properties and two constructors:
public class Contact
{
public Contact(string name) { Name = name; Email = ""; }
public Contact(string name, string email) { Name = name; Email = email; }
public string Name { get; }
public string Email { get; }
}
Read against the message, Contact matches none of the three accepted shapes:
there is no parameterless constructor, there is more than one parameterized constructor,
and neither carries JsonConstructorAttribute. The message names the type
(Type 'Contact') and the path $, the root object, because the
failure happened before any property was read. The same message appears twice, once in
the outer exception and once in the inner one.
The fix
public class FixedContact
{
public FixedContact(string name) { Name = name; Email = ""; }
[JsonConstructor]
public FixedContact(string name, string email) { Name = name; Email = email; }
public string Name { get; }
public string Email { get; }
}
The JSON was {"Name":"Kwame Mensah","Email":"kwame@example.test"}, and
dotnet run -- fix deserialized it into FixedContact and printed:
Kwame Mensah kwame@example.test
Both values arrived: the parameter names name and email were
matched, ignoring case, to the properties Name and Email, which
carry the JSON values, and the class
body is otherwise the same as Contact. The attribute lives in
System.Text.Json.Serialization, so the file needs that using.
Put it on the constructor that takes every value you want from the JSON; here the
two-parameter one, so Email is filled from the JSON instead of set to an
empty string.
How it was reproduced
A console project from dotnet new console on .NET SDK 10.0.403
(net10.0, no extra packages; System.Text.Json is part of the framework), the
Contact class above and
JsonSerializer.Deserialize<Contact>(json) with default options. Run with
dotnet run for the error and dotnet run -- fix for the class with
the attribute.
Frequently asked
- Does System.Text.Json need a parameterless constructor?
- Not necessarily. The error message accepts three shapes: a parameterless constructor, a single parameterized constructor, or a parameterized constructor marked with JsonConstructorAttribute. A class with two parameterized constructors and none marked fails.
- Where do I put JsonConstructor?
- On the one constructor System.Text.Json should call, normally the one that takes every value the JSON carries. Add using System.Text.Json.Serialization at the top of the file.
- Why does the error say Path: $?
- The dollar sign is the root of the JSON document. The serializer failed while deciding how to create the object, before it read any property, so the path points at the root.
More decoded errors in the Fixes category. A related System.Text.Json limit, for properties typed as an interface, is in Deserialization of interface or abstract types is not supported.