为了账号安全,请及时绑定邮箱和手机立即绑定

我可以使用 System.Text.Json 通过私有构造函数反序列化 Json 吗?

我可以使用 System.Text.Json 通过私有构造函数反序列化 Json 吗?

PHP
扬帆大鱼 2024-01-20 16:05:07
想知道是否可以拥有私有构造函数并使用新的 System.Text.Json 序列化器。public class MyModel{    public string Name { get; set; }    public string Data { get; set; }    private MyModel()     {        // use me for when deserializing    }    public MyModel(string name, string data)    {        Name = name;        Data = data;    }}简单的往返。var model = new MyModel("doo", "doo");var json = JsonSerializer.Serialize(model, new JsonSerializerOptions{    WriteIndented = true});// no to go because of there is no parameterless constructor defined for this object.var rehydrated = JsonSerializer.Deserialize<MyModel>(json);
查看完整描述

3 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

.NET 8.0 中的更新

只需添加JsonConstructorAttribute到私有构造函数中,如下所示:


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;

   }

}


.NET 7.0 中的更新

从 .NET 7.0 开始,可以通过编写自己的 ContractResolver 使用私有无参数构造函数来完成反序列化,如下所示:


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;

   }

}

使用方法如下:


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;

   }

}


查看完整回答
反对 回复 2024-01-20
?
慕容3067478

TA贡献1773条经验 获得超3个赞

答案似乎是“否”,或者至少是“还没有”。

这是[System.Text.Json] v1的 System.Text.Json 序列化程序的已知限制。我们计划将来支持这一点。 -阿松汗

您可以为此编写一个自定义转换器...对于[ASP.NET Core] 3.0 版本,没有计划在反序列化期间调用非默认构造函数的额外支持。这必须由定制转换器来完成。——史蒂夫哈特

链接的自定义转换器选项将允许您使用您拥有的任何 API 来构建对象,但与 Newtonsoft.Json 或实体框架通过摆弄反射和私有构造函数可以完成的操作不同,所以可能不是你在寻找什么。


查看完整回答
反对 回复 2024-01-20
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

您需要使用 JsonConstructor 属性。

查看完整回答
反对 回复 2024-01-20
  • 3 回答
  • 0 关注
  • 35 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信