json最大长度限制_api接口返回动态的json格式?我太难了,尝试一下 linq to json

一:背景

1. 讲故事

前段时间和一家公司联调api接口的时候,发现一个奇葩的问题,它的api返回的json会动态改变,简化如下:


{"Code":101,"Items":[{"OrderTitle":"订单1"}]}

{"Code":102,"Items":[{"ProductTitle":"商品1"}]}

逻辑是这样的: Items 中的内容会随的 Code 的改变而改变,里面有可能是订单列表又有可能是商品列表,习惯弱类型的朋友看这种json太正常不过了,但对于强类型的我们来说,简直就是一个大写的奇葩,你这让我用什么强类型反序列化呢???,如果还没理解,请看下面的这张图吧!

e1e29875b467bf8fedc6d12020e9763d.png

经过沟通,对方果然用的是弱类型的php,磨了半天,说服让对方改了返回结构,这样就可以直接用固有类匹配。

二:寻找解决办法

从业务上来说,能说服对方让步那是最好的,但从技术上来说,这种场景有什么好的解决办法呢?问题的本质就是json是动态的,你反序列化的时候无法指定匹配类。

1. 使用 dynamic

既然是动态的,那C#中也有一个动态类型 dynamic,何不用它来做json中动态变化的那部分的接受值,将 items 定义为 dynamic。如下图:

0509cfa63bba1fdc01b643ba1b1d6008.png

从图中看: rsp.Items as List 返回是null,尝试失败,虽然转化失败了,但我相信你也看到了 Newtonsoft.Json.Linq.JArray,貌似这玩意可以用 linq 操控,对的, 这就是 linq to json

2. 使用 linq to json

有了linq基础,提取JArray中内容就不难了,接下来把代码改成如下:


static void Main(string[] args){
var json = "{\"Code\":101,\"Items\":[{\"OrderTitle\":\"订单1\"}]}";

var rsp = JsonConvert.DeserializeObject(json);if (rsp.Code == 101)
{var items = (rsp.Items as JArray).Select(m => m["OrderTitle"].Value<string>()).ToList();
Console.WriteLine(string.Join(",", items));
}if (rsp.Code == 102)
{//todo ....
}
}

ffb80da49a9d2ad00371f26825fdebdd.png

从代码中可以看到,我是通过code的不同做了不同的业务逻辑处理,貌似问题通过这种半自动化的model实现了,但拥有强大好奇心的你,岂能不往下挖?

三:linq to json 分析

1. 好处

我觉得 linq to json 的最大好处就是绕过了强类型限制,可以像弱类型语言一样处理生成和读取json,给了我们在业务处理上更多的选择余地,接下来我就在Create和Query上给大家抛砖引玉吧。

2. 生成json

在没有强类型的情况下,如何构建json结构呢?对了,不知道大家对 linq to xml 还有熟悉的吗?还记得它是怎么一步一步构建的哈,如果你记得的话,这里也是差不多的构建方式,比如说刚才的 JArray。


JObject json = new JObject(
new JProperty("Code", 101),
new JProperty("Items", new JArray(new JObject()
{
new JProperty("OrderTitle","订单1"),
new JProperty("Created",DateTime.Now)
}))
);

Console.WriteLine(json.ToString());

7c47d95202b8c152a7b9181a57810fde.png

从图中看这种手工构建json的方式还是比较繁琐的,走的就是 linq to xml 的路子,有没有更简单的方式呢?我觉得这里你可以用 C# 中的一个语法糖:匿名类型,虽然从 IL 上看也是强类型,但在用在这里太合适了,接下来我来改造一下:


JObject json = JObject.FromObject(new
{
Code = 101,
Items = (new[]
{
new { OrderTitle="订单1",Created=DateTime.Now }
}).ToList()
});

Console.WriteLine(json.ToString());

ade632ee7979fd5fc2fb7e229956cc5e.png

这样是不是太方便了,算是巧用 匿名类型 吧。

2. 解析json

为了让结果更可观,我准备生成一个稍微复杂一点的json,然后通过 linq to json 和 jsonpath 两种方式操控json。


{
"store":{
"book":[
{
"category":"reference",
"author":"Nigel Rees",
"title":"Sayings of the Century",
"price":8.95
},
{
"category":"fiction",
"author":"Evelyn Waugh",
"title":"Sword of Honour",
"price":12.99
},
{
"category":"fiction",
"author":"Herman Melville",
"title":"Moby Dick",
"isbn":"0-553-21311-3",
"price":8.99
},
{
"category":"fiction",
"author":"J. R. R. Tolkien",
"title":"The Lord of the Rings",
"isbn":"0-395-19395-8",
"price":22.99
}
],
"bicycle":{
"color":"red",
"price":19.95
}
}
}
  • 对 category 进行分组,统计每个类别的总金额


static void Main(string[] args){
var json = System.IO.File.ReadAllText("1.txt");

JObject obj = JObject.Parse(json);

var dict = obj["store"]["book"].GroupBy(m => m["category"])
.ToDictionary(k => k.Key,
v => v.Select(n => n.Value<decimal>("price")).Sum());

foreach (var key in dict.Keys)
{
Console.WriteLine($"key={key},value={dict[key]}");
}
}

9286fce54793a0d4895c9798d4313272.png

哈哈,分组统计在强大的linq面前就是这么简单!

  • 使用 jsonpath 处理

jsonpath 就像 xmlpath 一样,非常强大,更多的功能可以参考这个网页:https://goessner.net/articles/JsonPath/。

520a01ee59b2e6f200bf97cc30569f8b.png

根据上面的语法,我尝试着提取所有的price,使用 $..price 试试。


var json = System.IO.File.ReadAllText("1.txt");

JObject obj = JObject.Parse(json);

var priceList= obj.SelectTokens("$..price");

foreach (var price in priceList)
{
Console.WriteLine(price.Value<decimal>());
}

8126e44ee9458065d3a0dcd3cf67cef3.png

四:总结

我相信大家在90%的情况都是用强类型作为json的mapping,剩下的10%情况,可以了解下强大的 linq to json哈,太实用啦!希望本篇对您有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux命令英文全称解释【转载】

Filesystem Hierarchy Standard(FHS) /&#xff1a;根目录&#xff0c;所有的目录、文件、设备都在/之下&#xff0c;/就是Linux文件系统的组织者&#xff0c;也是最上级的领导者。 /bin&#xff1a;bin 就是二进制&#xff08;binary&#xff09;英文缩写。在一般的系统当中…

python表格数据的储存和读取_python读取表格存储

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技术人对外发布原创技术内容的最大平台&…

Linux的实际操作:文件目录类的实用指令 (显示路径pwd 显示文件ls 更改目录cd)

文件目录类的相关指令汇总&#xff1a;&#xff08;后续会有更新&#xff09; 1.pwd指令 pwd 功能&#xff1a;显示当前工作目录的绝对路径 2.ls指令 ls ls 横向排列出所有不隐藏的文件与文件夹 ls -l ls -l 以列表的方式显示不隐藏的文件与文件夹的详细信息 ls -a ls -a…

前端wxml取后台js变量值_微信小程序云开发教程WXML入门数据绑定

同学们大家好&#xff0c;我是小伊同学&#xff0c;今天带领大家学习WXML部分一个重要的知识点&#xff0c;数据绑定。简单来讲&#xff0c;数据绑定就是通过双重花括号将一个变量绑定到界面上。首先&#xff0c;我们为什么要将变量绑定到页面上呢&#xff1f;因为在制作一个小…

Linux的实际操作:文件目录类的实用指令(创建目录mkdir 删除目录rmdir 递归删除目录rm -rf)

有时候我们会发现&#xff0c;Linux自带的层级结构的目录就那么几个&#xff0c;但是我们日常使用中不可能就这么几个而已&#xff0c;因此我们还需要主动去创建目录&#xff0c;相当于在原有路径的基础上&#xff0c;创建目录&#xff0c;这个目录值得是文件夹 1.mkdir 目录 …

python重定向cookie_模拟登陆中 302 重定向和 cookies 的一些困惑

我想写一个查询话费和流量的爬虫&#xff0c;关键是实现模拟登陆的这个部分。在登陆过程中&#xff0c;点击登陆之后&#xff0c;登陆表单会 post 到一个地址(这一步浏览器不显示)&#xff0c;然后会 302 跳转到登陆成功的页面。我现在想得到登陆成功的 cookies &#xff0c;不…

python变量名称的规定_Python 趣闻:如何获得变量的名字?

获取变量名今天我们探讨Python中一个看似很简单&#xff0c;实则并不容易的问题。这个问题是&#xff1a;如何获得变量的名字&#xff1f;举例说明&#xff0c;给定一个变量var&#xff0c;给它赋值字符串"foo"。即In [1]: var "foo"现在我们需要得到变量…

举例子说明什么是迭代什么是递归【转载】

举个例子bai&#xff1a;我想求1234..100的值。 迭代的做法&#xff1a;从1到100&#xff0c;顺着往下累加。123,336,6410,10515…… 程序表示&#xff0c; int i1,sum0; while(i<100){ sum sum i; } 递归的做法&#xff1a;我要求1到100的累加值&#xff0c;如果我已经得到…

Linux的实际操作:文件目录类的实用指令(touch cp)

1.touch 空文件 在当前路径下创建空文件 注意&#xff1a;mkdir是创建文件夹&#xff0c;touch是创建文件 那么有同学要问了&#xff0c;这个和上一章讲的vim创建一个文件有什么区别&#xff1f; 区别&#xff1a;vim创建完直接打开文件&#xff0c;touch不会直接…

loss下降auc下降_梯度下降算法 线性回归拟合(附Python/Matlab/Julia源代码)

梯度下降梯度下降法的原理梯度下降法(gradient descent)是一种常用的一阶(first-order)优化方法&#xff0c;是求解无约束优化问题最简单、最经典的方法之一。梯度下降最典型的例子就是从山上往下走&#xff0c;每次都寻找当前位置最陡峭的方向小碎步往下走&#xff0c;最终就会…

台式电脑耳机插孔在哪_吉林戴尔电脑音箱维修app,查看详情_曹操闪修

首页 > 新闻列表 > 正文发布时间&#xff1a;2020-10-24 01:14:13 浏览&#xff1a; 14导读&#xff1a;吉林戴尔电脑音箱维修app, 这样的问题一般只有三种解决方法&#xff0c;一种就是重新新冲突的驱动。第二种方法就是在中改变各自的中断&#xff0c;消除冲突。第三种…

Linux的实际操作:文件目录类的实用指令(rm mv)

其实rm和我们上几节学到的rmdir有点类似 &#xff0c;区别在哪里呢&#xff1f;rm是可以删除文件或者文件夹&#xff0c;rmdir是删除文件夹&#xff0c;而且如果是一个非空文件夹&#xff0c;是不能通过rmdir删除的&#xff0c;需要用rm -rf 去强制递归删除&#xff08;不懂的话…

无法将该对象添加到ldap服务器_LDAP 基础知识

LDAP 基础知识目录简介协议概览目录结构架构&#xff08;Schema&#xff09;对象类&#xff08;objectClass&#xff09;属性&#xff08;Attribute&#xff09;条目&#xff08;Entry&#xff09;LDAP 中的数据常用命令启动和关闭: start-ds / stop-ds检查 LDAP 服务器状态: s…

windows7系统损坏修复_【软件资讯】还在用win7?微软Windows 7系统正式停止技术支持...

本文转自IT之家&#xff0c;作者玄隐。早在2015年1月&#xff0c;微软结束了对Windows 7的主流支持&#xff0c;该公司停止向旧操作系统添加新功能。微软将Windows 7从主流支持转移到扩展支持。2020年1月14日&#xff0c;今天迎来了Windows 7的停止技术支持&#xff0c;微软将把…

Linux的实际操作:文件目录类的实用指令(cat more less)

1.cat 要查看的文件 &#xff08;是以只读的方式打开,区别于vim可以查看文件并且编辑&#xff09; cat -n 要查看的文件 &#xff08;只读&#xff0c;且提供行号&#xff09; cat -n 要查看的文件 | more &#xff08;这个操…

python中pickle模块_Python pickle模块的用法

串行化主要用于网络传输或者持久化。我们知道&#xff0c;网络上的数据都是字节流&#xff0c;如果希望将某个对象传送给远端的机器&#xff0c;首先就必须将其转换成字节流&#xff0c;然后才可以在网络上传输。文件也是字节流&#xff0c;如果希望将某个对象保存到文件中&…

电子测量与仪器第四版pdf_准确选择表面粗糙度仪的测量参数应该从哪些地方着手好【电子仪器吧】...

表面粗糙度仪的参数怎么选择&#xff1f;首先要先满足运用功能要求&#xff0c;其次再兼顾经济性能。即&#xff0c;在满足运用要求的前题下&#xff0c;尽可能下降外表粗糙度要求&#xff0c;放大表面粗糙度允许值。对多数外表面来说&#xff0c;给出高度特色评定参数即可反映…

Linux的实际操作:文件目录类的实用指令(重定向“>“和追加“>>“)

1. > 表示重定向 &#xff08;重定向什么意思呢&#xff1f;就是把一个文件的内容&#xff0c;保存到指定的位置&#xff09; > 是定向输出到文件&#xff0c;如果文件不存在&#xff0c;就创建文件&#xff1b;如果文件存在&#xff0c;就将其清空&#…

wrapper怎么用_用责任链模式设计拦截器

我在 Redant(https://github.com/all4you/redant) 中通过继承 ChannelHandler 实现了拦截器的功能&#xff0c;并且 pipeline 就是一种责任链模式的应用。但是我后面对原本的拦截器进行了重新设计&#xff0c;为什么这样做呢&#xff0c;因为原本的方式是在 ChannelHandler 的基…

VS2019 配色_这个双11,凯里-欧文陪你过!欧文6正式发布,城市版配色真的香

北京时间11月5日&#xff0c;在篮网主场对阵鹈鹕的比赛中&#xff0c;欧文一上场就让教主眼前一亮&#xff0c;这鞋骚的有点过分啊。欧文6代已经于北京时间11月5日正式发布&#xff0c;虽然首发配色毫无惊喜&#xff0c;毕竟早在休赛期就已经被曝得连底裤都不剩了&#xff0c;但…