Update in .NET 8.0
Just add JsonConstructorAttribute
to the private constructor as follows:
public class Employee
{
[JsonConstructor] // This will work from .NET 8.0
private Employee()
{
}
private Employee(int id, string name)
{
Id = id;
Name = name;
}
[JsonInclude]
public int Id { get; private set; }
[JsonInclude]
public string Name { get; private set; }
public static Employee Create(int id, string name)
{
Employee employee = new Employee(id, name);
return employee;
}
}
Update in .NET 7.0
From .NET 7.0, deserialization can be done with a private parameterless constructor by writing your own ContractResolver as follows:
public class PrivateConstructorContractResolver : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object && jsonTypeInfo.CreateObject is null)
{
if (jsonTypeInfo.Type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).Length == 0)
{
// The type doesn't have public constructors
jsonTypeInfo.CreateObject = () =>
Activator.CreateInstance(jsonTypeInfo.Type, true);
}
}
return jsonTypeInfo;
}
}
Use as follows:
private static void Main(string[] args)
{
JsonSerializerOptions options = new JsonSerializerOptions
{
TypeInfoResolver = new PrivateConstructorContractResolver()
};
Employee employee = Employee.Create(1, "Tanvir");
string jsonString = JsonSerializer.Serialize(employee);
Employee employee1 = JsonSerializer.Deserialize<Employee>(jsonString , options);
}
public class Employee
{
private Employee()
{
}
private Employee(int id, string name)
{
Id = id;
Name = name;
}
[JsonInclude]
public int Id { get; private set; }
[JsonInclude]
public string Name { get; private set; }
public static Employee Create(int id, string name)
{
Employee employee = new Employee(id, name);
return employee;
}
}