Json serializer code generator doesn't support internal constructors (original) (raw)
Description
If I have a public class that I want to be able to deserialize, but I don't want that class publicly constructable, I can no longer deserialize it, even though the generated deserializer code has access to the internal constructor.
This issue prevents moving from DataContractJsonSerializer
to S.T.J.
Reproduction Steps
In a console app, add the following code:
using System.Text.Json; using System.Text.Json.Serialization;
string json = "{"name":"Hello World"}";
var obj = JsonSerializer.Deserialize(json, MyDataModelSerializationContext.Default.MyDataModel);
[JsonSerializable(typeof(MyDataModel))] [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] internal partial class MyDataModelSerializationContext : JsonSerializerContext { }
public class MyDataModel { // [JsonConstructor] Won't make a difference internal MyDataModel() { } public string? Name { get; set; } }
Expected behavior
Object deserializes.
Actual behavior
Exception thrown on deserialize:
System.NotSupportedException: 'Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MyDataModel'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.'
Looking at the generated code, you'll note the ObjectCreator
is null.
Compare that to when the constructor is declared public:
Related
A similar issue is hit with a data model like this:
internal class MyDataModel { [JsonPropertyName("name")] public string? Name { get; internal set; } }
In this case for this internal class, a setter isn't generated for the Name property and during serialization the value is never defined. Granted in this case there's no need to mark it internal since the entire class is already internal - however even if the class is public, I can't restrict the setter from public abuse and only allow the deserializer to set it.
Regression?
No response
Known Workarounds
Not really. If I make the entire class internal (and make the constructor public albeit it is effectively internal now), it works again. However I do want my class to be publicly accessible
Configuration
.net 6.0.401
Other information
No response