首页 新闻 会员 周边 捐助

Newtonsoft.Json怎么根据属性的值决定是否忽略该属性?

0
悬赏园豆:10 [待解决问题]
var obj = new { i = -1 };
var json = JsonConvert.SerializeObject(obj);
Assert.AreEqual(json, "{}");

比如当i的值是-1的时候,就忽略这个属性。

var obj = new { i = 1 };
var json = JsonConvert.SerializeObject(obj);
Assert.AreEqual(json, "{\“i\”:1}");

当i不是-1的时候就正常序列化。

百香居士的主页 百香居士 | 初学一级 | 园豆:137
提问于:2020-05-17 20:21
< >
分享
所有回答(2)
0
dudu | 园豆:31030 (高人七级) | 2020-05-17 20:31

这个例子只使用了反射信息,并没有提到对于当前属性值得动态判断...

支持(0) 反对(0) 百香居士 | 园豆:137 (初学一级) | 2020-05-17 20:51
0

不知道你的需求是什么,感觉没必要啊。多一个属性就多一个呗,消费方就当不存在不用就是了。

这种根据值来动态决定有哪些属性只会带来一些不必要的麻烦。比如有些字段是null的,有些地方就想着给忽略掉,但是对于前端js来说,就有差异了,前者是null,后者则就是undefined了。

Timetombs | 园豆:3954 (老鸟四级) | 2020-05-17 20:59

就是因为C#中只有有值和null值两种,才需要用忽略属性去表达undefined,否则就得用null加上ignore null去表达undefined,但是null又可以是null,就有歧义了。

总之就是C#没有办法同时表达null和undefined,所以我在想办法表达undefined(null就默认表达为null)。

支持(0) 反对(0) 百香居士 | 园豆:137 (初学一级) | 2020-05-17 21:10

至于为什么需要undefined,很简单的场景就是修改一个对象,用undefined表达不修改这个属性。

比如User有Company和Age两个属性,你只想修改Age而不想修改Company,那这个参数就可以是

{Age: 18}

Company是undefined就是表达忽略的语义。

支持(0) 反对(0) 百香居士 | 园豆:137 (初学一级) | 2020-05-17 21:16

@百香居士: 前端只修改age, 只发送这一个字段没问题。但是后端拿一个完整的class去做映射,这就不合适了,这会使得使得应用变得很“脆弱”(依赖隐含的逻辑来表达修改还是不修改),而且增加对对前端的要求(不能有多余的字段传输过来),两头都有假设(假设不传字段就是不修改)。这不太符合宽进严出的接口策略。

我的建议有2个方案:

  1. 前端发送所有的字段,即使不修改,保持原样就是了(前端打开编辑页面时就已经可得到所有的字段了)。
  2. 为单独修改的字段增加独立的接口。

选哪个都行。我认为还是1直观省事并且一致性强,而且没有任何的隐含的条件在里面。如果你担心每次修改多余的字段不合适,那么后端修改前查询出最新的数据,比对一下哪些需要修改就行了。看起来时麻烦了一些,但是没有隐含的假设的逻辑,也使得接口更加健壮。

支持(1) 反对(0) Timetombs | 园豆:3954 (老鸟四级) | 2020-05-17 22:14

@blackheart: 假设本来就是不可避免的,就是不知哪来的隐含一说。没有该字段即是忽略,是很明确也很明显的逻辑。即使没有“缺省即是忽略”,很多时候也都是定义为“缺省即是为空”,这对后端才是真正的隐含假设,不管是Newtonsoft还是.Net Core的Json库,默认设置都是如此。而且这种情况就不安全得多。

而“多余的字段”并不成立,如果前端将原值做为修改值传递,这就跟你说的方案1一样;如果前端将空值传递,那对于你的方案1来说,就是置空,对于我这个方案来说也是如此。所以对于一个动态字段的DTO,本身就是静态字段的DTO的超集,不存在做到静态做不到的事情,只是对静态语言的后端来说实现更复杂一些而已。我觉得相比之下,语义更清晰也更简洁,同时也不需要先查询后修改,节省开销。

后端也不会拿一个模型类去映射,而是每个可修改的字段都包了一层Option<T>在装进DTO里,是借用的函数式的概念,我现在就是在开发这个Option类型。

支持(0) 反对(0) 百香居士 | 园豆:137 (初学一级) | 2020-05-18 00:05
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册