RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1017981
Accepted
A K
A K
Asked:2020-08-28 02:08:15 +0000 UTC2020-08-28 02:08:15 +0000 UTC 2020-08-28 02:08:15 +0000 UTC

在控制器中反序列化具有私有集的字段[关闭]

  • 772
关闭 这个问题是题外话。目前不接受回复。

该问题是由不再复制的问题或错字引起的。虽然类似问题可能与本网站相关,但该问题的解决方案不太可能帮助未来的访问者。通常可以通过在发布问题之前编写和研究一个最小程序来重现问题来避免此类问题。

3年前关闭。

改进问题

Json.Net 库支持通过反射设置具有私有集的字段,因此这两个选项都工作得很好:

public class Abc1
{
    public int Id { get; set; }
    public string Title { get; set; }
}

public class Abc2
{
    public Abc2(int id, string title)
    {
        Id = id;
        Title = title;
    }

    public int Id { get; private set; }
    public string Title { get; private set; }
}

void Main()
{
    var request = new Abc1 { Id = 1, Title = "Test" };
    Execute(request);

    var request = new Abc2(1, "Test");
    Execute(request);
}

private void Execute<T>(T request)
{
    var requestSerialized = JsonConvert.SerializeObject(request);

    var deserialized = JsonConvert.DeserializeObject<T>(requestSerialized);

    request.Dump();
    requestSerialized.Dump();
    deserialized.Dump();
}

然而,尽管从 1.0 版到 2.2 版的 asp.net 核心已将 json.net 内置为常规 json 处理程序,但无法在控制器中使用没有默认构造函数的类:

[HttpPost]
public async Task<object> Update([FromBody] City.Update.Command command, CancellationToken cancellationToken)
{
    var result = await this.Mediator.Send(command, cancellationToken);
    return result;
}

如果Command 没有默认构造函数,而只有一个私有 set,我们将得到 null,字段不会被设置。

为什么会这样,如何纠正?

在asp.net core 3.0 中可以使用:

services.AddMvc().AddNewtonsoftJson();

但是我还没有测试过beta。

团队:

using MediatR;

namespace Application.City.Update
{
    public class Command : IRequest<CityData>
    {
        public Command(CityData city)
        {
            this.City = city;
        }

        public CityData City { get; private set; }
    }

    public class CityData
    {
        public CityData()
        {
        }

        public CityData(City city)
        {
            this.Id = city.Id;
            this.Title = city.Title;
        }

        public int Id { get; set; }

        public string Title { get; set; }

        public City ToEntity()
        {
            return new City
            {
                Id = this.Id,
                Title = this.Title,
            };
        }
    }
}
c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    A K
    2020-08-28T15:46:42Z2020-08-28T15:46:42Z

    如果有任何东西是对问题的回答,而不是对答案的补充。:)

    总的来说,我似乎对 Json.Net 如何处理私有集的确切含义没有完全准确的理解。原则上,他会这样做,是的,但是一旦涉及复合对象,细微差别就开始了。

    这是一个比问题更扩展的示例:

    public class Abc1
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public DataDto1 Data { get; set; }
    }
    
    public class DataDto2
    {
        public DataDto2(string noteA, string noteB, string myProperty)
        {
            this.NoteA = noteA;
            this.NoteB = noteB;
            this.Ano = new AnotherDto2(myProperty);
        }
    
        public string NoteA { get; private set; }
        public string NoteB { get; private set; }
        public AnotherDto2 Ano { get; set; }
    }
    
    public class DataDto1
    {
        public string NoteA { get; set; }
        public string NoteB { get; set; }
        public AnotherDto1 Ano { get; set; }
    }
    
    public class AnotherDto2
    {
        public AnotherDto2(string myProperty)
        {
            MyProperty = myProperty;
        }
    
        public string MyProperty { get; private set; }
    }
    
    public class AnotherDto1
    {
        public string MyProperty { get; set; }
    }
    
    void Main()
    {
        var request = new Abc1 { Id = 1, Title = "Test", Data = new DataDto1 { NoteA = "tA", NoteB = "tB", Ano = new AnotherDto1 { MyProperty = "myPr"} } };
        Execute(request);
    
        var request = new Abc2(1, "Test", "tA", "tB", "myPr");
        Execute(request);
    }
    

    虽然一切正常:

    在此处输入图像描述

    但是,如果您更改 DataDto2 类上的复合属性的定义,则不会设置它:

    public AnotherDto2 Ano { get; private set; }
    

    在此处输入图像描述

    类似地,如果您在类的顶层声明一个私有集,那么链上的所有内容都将为空。

    同时,顶层的原始类型根本不会对更改字段的可见性做出反应。

    总的来说,考虑到我的 CityData 是一个扁平的 Dto,它总是只包含原始类型(int、string、DateTime),你可以按如下方式获取:

    [HttpPost]
    public async Task<object> Update([FromBody] City.Update.CityData data, CancellationToken cancellationToken)
    {
        var command = City.Update.Command(data);
        var result = await this.Mediator.Send(command, cancellationToken);
        return result;
    }
    

    然后可以使命令完全 get only:

    public class Command : IRequest<CityData>
    {
        public Command(CityData city)
        {
            this.City = city;
        }
    
        public CityData City { get; }
    }
    

    对于 CityData,删除构造函数并将所有字段放入私有集中:

    public class CityData
    {
        public CityData(City city)
        {
            this.Id = city.Id;
            this.Title = city.Title;
        }
    
        public int Id { get; private set; }
    
        public string Title { get; private set; }
    
        public City ToEntity()
        {
            return new City
            {
                Id = this.Id,
                Title = this.Title,
            };
        }
    }
    

    更新。或者

    如果你设置了属性,那么序列化会再次被选中:

    [JsonProperty]
    public AnotherDto2 Ano { get; private set; }
    

    Update2 感谢@PavelMayorov 为该问题提供了另一个很好的解决方案[JsonConstructorAttribute]:(文档)

    Update3 感谢@Grundy 的帮助,他第一个指出上面的代码应该反序列化。实际上,问题中的示例不是我正在运行的代码的精确副本,并且视图很模糊,我没有考虑最终影响不同答案的微小差异。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5