当前位置: 首页 > 知识库问答 >
问题:

在反序列化过程中不使用内部构造函数

易俊驰
2023-03-14

我正在编写一个库来访问用于管理后端系统中数据的网络应用编程接口。该库还将为类提供正确管理数据的逻辑。由于这个原因,大多数类不能有属性的公共设置器或接受所有属性的公共构造函数。相反,我试图使用一个具有内部访问修饰符的构造函数,它可以设置所有属性。

当试图使用System反序列化JSON字符串时。文本。json它将忽略内部构造函数-它将使用其他构造函数或抛出异常。我还尝试用[JsonConstructor]注释内部构造函数,但它什么也做不了。

具有内部构造函数的示例类:

public class Entry
{
    public int Id { get; }

    public string Name { get; set; }
    public string Value { get; set; }


    [JsonConstructor]
    internal Entry(int id, string name, string value)
    {
        this.Id = id;
        this.Name = name;
        this.Value = value;
    }
}

假设用户可以使用库从后端获取一个Entry,修改它的名称和值,并更新它。用户不应该能够更改Id属性或创建新的Entry

反序列化示例:

var json = "{\"id\": 1337, \"name\": \"TestEntry\", \"value\": \"TestValue\"}";
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);

var entry = JsonSerializer.Deserialize<Entry>(json, options);

调用JsonSeriazer。反序列化将抛出System.不支持在没有无参数构造函数、单数参数化构造函数或带注释的JsonConstructor属性的参数化构造函数的情况下对类型进行反序列化:

一种可能的解决方案是将构造函数公开,并使用[过时(“Message”,true)]属性对其进行注释-当尝试使用此构造函数时,编译器将抛出并出错,使构造函数不可用。但我觉得这不是最优雅的解决方案,它还滥用了[过时]属性。

有没有其他办法解决这个问题?


共有1个答案

端木明贤
2023-03-14

在这种情况下,实现这一点的最佳方法是使用单独的模型进行序列化。然后在Domain模型上使用内部构造函数。

public class EntryDto
{
    public int Id { get; }

    public string Name { get;  }
    public string Value { get; }


    [JsonConstructor]
    public EntryDto(int id, string name, string value)
    {
        this.Id = id;
        this.Name = name;
        this.Value = value;
    }
    
    public Entry ToDomainModel()
    {
      return new Entry(this.Id, this.Name, this.Value);
    }

}

public class Entry
{
    public int Id { get; }

    public string Name { get; }
    public string Value { get; }

    internal Entry(int id, string name, string value)
    {
        this.Id = id;
        this.Name = name;
        this.Value = value;
    }
}

```
 类似资料:
  • 问题内容: 我有一个发送到服务器或从服务器发送的用户对象。发送用户对象时,我不想将哈希密码发送给客户端。因此,我添加了password属性,但这也阻止了将其反序列化为密码,这使得在没有密码的情况下很难注册用户。 我怎样才能只应用序列化而不是反序列化?我使用的是Spring JSONView,因此对的控制不多。 我尝试过的事情: 添加到属性 仅添加getter方法 问题答案: 确切的操作方法取决于你

  • 我有一个用户对象,它被发送到服务器和从服务器发送。当我发出user对象时,我不想将散列密码发送给客户端。因此,我在password属性中添加了,但这也阻止了它反序列化为密码,这使得用户在没有密码时很难注册。 如何才能只让应用于序列化而不应用于反序列化?我使用的是Spring JSONView,所以我对没有太多的控制权。 将添加到属性 仅在getter方法上添加

  • 问题内容: 我有一个发送到服务器或从服务器发送的用户对象。发送用户对象时,我不想将哈希密码发送给客户端。因此,我添加了password属性,但这也阻止了将其反序列化为密码,这使得在没有密码的情况下很难注册用户。 我怎样才能只应用序列化而不是反序列化?我使用的是Spring JSONView,因此对的控制不多。 我尝试过的事情: 添加到属性 仅添加getter方法 问题答案: 确切的操作方法取决于你

  • 问题内容: 我正在尝试使用Jackson 1.9.10反序列化此类的实例: 当我尝试这个我得到以下 冲突的基于属性的创建者:已经有… {界面org.codehaus.jackson.annotate.JsonCreator @ org.codehaus.jackson.annotate.JsonCreator()}],遇到了…,注释:{接口org.codehaus。 jackson.annotat

  • 我有一个类,它有一个默认构造函数,还有一个重载构造函数,它接受一组参数。这些参数与对象上的字段匹配,并在构造时指定。此时,我需要用于其他目的的默认构造函数,因此如果可以的话,我希望保留它。 我的问题:如果我删除默认的构造函数并传递JSON字符串,对象反序列化正确,并传递构造函数参数没有任何问题。我最终以我所期望的方式找回填充的对象。但是,一旦我将默认构造函数添加到对象中,当我调用

  • 正在尝试从spring boot接收页面进行单元测试。如果与javascript一起使用,该页面可以很容易地进行反序列化,但是使用java,它会失败。已经为spring添加了一个默认构造函数(这是另一篇stackoverflow文章中接受的答案),但它在这里不起作用。 单元测试 再培训班 "' 代码在github上可用-- 反序列化引发以下错误: