json最大长度限制_api接口返回动态的json格式?我太难了,尝试一下 linq to json
一:背景
1. 講故事
前段時(shí)間和一家公司聯(lián)調(diào)api接口的時(shí)候,發(fā)現(xiàn)一個(gè)奇葩的問題,它的api返回的json會(huì)動(dòng)態(tài)改變,簡(jiǎn)化如下:
{"Code":101,"Items":[{"OrderTitle":"訂單1"}]}
{"Code":102,"Items":[{"ProductTitle":"商品1"}]}
邏輯是這樣的:?Items?中的內(nèi)容會(huì)隨的 Code 的改變而改變,里面有可能是訂單列表又有可能是商品列表,習(xí)慣弱類型的朋友看這種json太正常不過了,但對(duì)于強(qiáng)類型的我們來說,簡(jiǎn)直就是一個(gè)大寫的奇葩,你這讓我用什么強(qiáng)類型反序列化呢???,如果還沒理解,請(qǐng)看下面的這張圖吧!
經(jīng)過溝通,對(duì)方果然用的是弱類型的php,磨了半天,說服讓對(duì)方改了返回結(jié)構(gòu),這樣就可以直接用固有類匹配。
二:尋找解決辦法
從業(yè)務(wù)上來說,能說服對(duì)方讓步那是最好的,但從技術(shù)上來說,這種場(chǎng)景有什么好的解決辦法呢?問題的本質(zhì)就是json是動(dòng)態(tài)的,你反序列化的時(shí)候無法指定匹配類。
1. 使用 dynamic
既然是動(dòng)態(tài)的,那C#中也有一個(gè)動(dòng)態(tài)類型 dynamic,何不用它來做json中動(dòng)態(tài)變化的那部分的接受值,將?items?定義為 dynamic。如下圖:
從圖中看:?rsp.Items as List?返回是null,嘗試失敗,雖然轉(zhuǎn)化失敗了,但我相信你也看到了?Newtonsoft.Json.Linq.JArray,貌似這玩意可以用 linq 操控,對(duì)的, 這就是?linq to json。
2. 使用 linq to json
有了linq基礎(chǔ),提取JArray中內(nèi)容就不難了,接下來把代碼改成如下:
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 ....
}
}
從代碼中可以看到,我是通過code的不同做了不同的業(yè)務(wù)邏輯處理,貌似問題通過這種半自動(dòng)化的model實(shí)現(xiàn)了,但擁有強(qiáng)大好奇心的你,豈能不往下挖?
三:linq to json 分析
1. 好處
我覺得 linq to json 的最大好處就是繞過了強(qiáng)類型限制,可以像弱類型語(yǔ)言一樣處理生成和讀取json,給了我們?cè)跇I(yè)務(wù)處理上更多的選擇余地,接下來我就在Create和Query上給大家拋磚引玉吧。
2. 生成json
在沒有強(qiáng)類型的情況下,如何構(gòu)建json結(jié)構(gòu)呢?對(duì)了,不知道大家對(duì)?linq to xml?還有熟悉的嗎?還記得它是怎么一步一步構(gòu)建的哈,如果你記得的話,這里也是差不多的構(gòu)建方式,比如說剛才的 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());
從圖中看這種手工構(gòu)建json的方式還是比較繁瑣的,走的就是?linq to xml?的路子,有沒有更簡(jiǎn)單的方式呢?我覺得這里你可以用 C# 中的一個(gè)語(yǔ)法糖:匿名類型,雖然從?IL?上看也是強(qiáng)類型,但在用在這里太合適了,接下來我來改造一下:
JObject json = JObject.FromObject(new
{
Code = 101,
Items = (new[]
{
new { OrderTitle="訂單1",Created=DateTime.Now }
}).ToList()
});
Console.WriteLine(json.ToString());
這樣是不是太方便了,算是巧用 匿名類型 吧。
2. 解析json
為了讓結(jié)果更可觀,我準(zhǔn)備生成一個(gè)稍微復(fù)雜一點(diǎn)的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
}
}
}
對(duì) category 進(jìn)行分組,統(tǒng)計(jì)每個(gè)類別的總金額
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]}");
}
}
哈哈,分組統(tǒng)計(jì)在強(qiáng)大的linq面前就是這么簡(jiǎn)單!
使用 jsonpath 處理
jsonpath 就像 xmlpath 一樣,非常強(qiáng)大,更多的功能可以參考這個(gè)網(wǎng)頁(yè):https://goessner.net/articles/JsonPath/。
根據(jù)上面的語(yǔ)法,我嘗試著提取所有的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>());
}
四:總結(jié)
我相信大家在90%的情況都是用強(qiáng)類型作為json的mapping,剩下的10%情況,可以了解下強(qiáng)大的 linq to json哈,太實(shí)用啦!希望本篇對(duì)您有幫助。
總結(jié)
以上是生活随笔為你收集整理的json最大长度限制_api接口返回动态的json格式?我太难了,尝试一下 linq to json的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java算法的递归问题设计_java算法
- 下一篇: JAVA进阶教学之(IO流)