【问题标题】:Json with dynamic properties - deserialize into C# object具有动态属性的 Json - 反序列化为 C# 对象
【发布时间】:2017-08-27 23:11:02
【问题描述】:

当用户点击保存时,我有以下 JSON

tasks      : {
        updated : [
            { Id : 123, SomeField1 : 'new value', SomeField2 : 'new value', SomeField3 : 'new value' },
            { Id : 125, SomeField2 : 'new value' },
            { Id : 127, SomeField1 : 'new value', SomeField4 : 'new value' },
            { Id : 129, SomeField2 : 'new value', SomeField3 : 'new value' },
            { ................ }
        ],
        removed : [
            { Id : 345 },
            { Id : 847 }
        ]
    }

在 MVC 服务器端 (C#),我有一个 ViewModel,.NET 将它反序列化回我的 viewmodel 对象。 在这个例子中,这个对象有 Id, SomeField1, SomeField2, SomeField3, SomeField4。

我遇到的问题是客户端只发送实际更新的字段,所以如果用户从未更新 SomeField3 它不会在 json 中,并且 .NET 对于该数组对象将有一个 null 作为 SomeeField3 ...

所以我无法获取记录,将所有字段更新为视图模型,然后调用更新,因为它将 SomeField3 设置为 null ,这是不正确的 - 该字段中可能存在用户刚刚没有的数据在这种情况下触摸..(在另一种情况下,他们可能已经删除了他们的文本,那么更新将是有效的..

我不确定解决此问题的最佳方法是什么。 期待您的建议。

【问题讨论】:

  • 你是用EF保存记录吗?
  • 是的,EF(代码优先)和 UnitOfWork。
  • 您可以使用 .IsModified 属性更新字段,仅在 db 中更改,例如 db.Entry(sometable).Property(x => x.somefield).IsModified = true;
  • 在服务器端,我正在获取对象,然后在调用更新之前将视图模型中的值分配给对象。我有点需要知道每个属性的视图模型上的 IsModified 标志,所以我知道它是否由反序列化器设置...
  • 是的,它用于更新没有空值的属性。

标签: c# json asp.net-mvc dynamic deserialization


【解决方案1】:

我建议你在 API 操作中发布更新的字符串,然后你可以得到你的解决方案: 创建动态属性映射函数:

    public static class DynamicToStatic
    {
     public static T ToStatic<T>(object source, T destination)
     {
        var entity = destination;

        //source implements dictionary
        var properties = source as IDictionary<string, object>;

        if (properties == null)
            return entity;

        foreach (var entry in properties)
        {
            var propertyInfo = entity.GetType().GetProperty(entry.Key);
            if (propertyInfo != null && entry.Value != null)//Check property and its values exist or not ,change only when source contains value
                propertyInfo.SetValue(entity, entry.Value, null);
        }
        return entity;
    }
 }

将您的请求 json 转换为动态对象,然后将动态对象映射到您的静态类类型模型、从您的数据库记录初始化的类类型模型或根据您的要求的任何源。

//updatedJsonObjectString bound from request post data(JSONSTRINGIFY of post data)
dynamic source = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(updatedJsonObjectString);
Class1 model = new Class1();//mapped/filled by data call
var retUser = DynamicToStatic.ToStatic<Class1>(source, model);

【讨论】:

  • 嗨,这个客户端工具发送的 Json 是在一个 json 请求中添加、更新和删除的(不确定我可以改变这个).. 所以我有一个对象公共类 SchedulerHelperSaveObject { public IEnumerable 添加了 { get;放; } 公共 IEnumerable 更新 { 获取;放; } 公共 IEnumerable 已移除 { 获取;放;然后我的视图模型使用这个视图任务或任何即时处理,我已经添加和删除了所有工作,它只是目前给我一些白发的编辑。
  • 你可以按照上面的方法,你可以在 DynamicToStatic.ToStatic() 实现中设置你的逻辑。
  • 目前正在努力将更新的记录作为字符串传递,因为发送数据的 api 是第 3 方,所以我只是通过 json 接收记录,正如我在问题中所示..发送任务,员工,每个人都有(添加,更新,删除)的数组。我的 mvc Action 上的视图模型具有这样的属性。
  • public IEnumerable 添加了 { get;放; } 公共 IEnumerable 更新 { 获取;放; } 公共 IEnumerable 已移除 { 获取;放; }
  • 如果我将更新更改为 ienumberable 它似乎不起作用
【解决方案2】:

如果您使用Newton Json 进行反序列化。 Newton Json DeserializeObject 方法有一个重载,它将 json string 和 JsonSerializerSettings 作为参数。 JsonSerializerSettings 具有NullValueHandling 和MissingMemberHandling 属性。

  • MissingMemberHandling:获取或设置缺失成员(例如 JSON 包含不是对象成员的属性)的处理方式 在反序列化期间。

  • NullValueHandling:获取或设置在序列化和反序列化过程中如何处理空值

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多