去年,我在一篇文章用原始方法解析復雜字符串,json一定要用JsonMapper么?中介紹了簡單的JSON解析的問題,那種方法在當時的環境是非常方便的,因為不需要生成實體類,結構很容易解析。但隨着業務的變化,也會碰到超級變態的JSON,如果還按照以前的思路,會把人搞抽風掉,一旦結構變化,又要重來。所以今天給大家介紹一個簡單的方法,輕輕松松搞定超級變態的JSON,雖然需要生成實體類。它就是開源的:JSON C# Class Generator組件。
.NET開源目錄:【目錄】本博客其他.NET開源項目文章目錄
本文原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_json_generator.html
1.復雜的JSON啥樣子?
看看下面這個圖,文本文件都是12K,嵌套多層,說實話,我是沒耐心看下去的。所以找了個工具結構化了一下。看圖對比:


2.使用JSON C# Class Generator介紹和使用
JSON C# Class Generator是一個從JSON文本中生成C#內的應用程序。項目地址:https://jsonclassgenerator.codeplex.com/ ,目前支持數組,對象,整形,單精度,布爾,字符串和空值符類型。
使用過程很簡單,如下圖官網的截圖所示:輸入命名空間,主類名,生成的cs文件目錄,以及類型即可。同時右邊還有可見性,和一些簡單的配置,簡單易懂。

下面看看我們演示的這個JSON的使用,是在網絡找到的一段演示JSON代碼,我自己用到的實際數據有些比這還復雜。首先我們把JSON復制到JSON C# Class Generator中,設置相關參數,如下圖所示,生成文件后,復制到項目中,下面我們可以寫測試代碼,看看起解析的格式:

說明一下,我們JSON反序列需要用到Newtonsoft組件,這個相信大部分都肯定比我熟悉。將生成的文件復制到項目中,並添加的引用,如下代碼就反序列化OK了。是不是So Easy?
//獲取jsonzifc
var json = File.ReadAllText("復雜JSON例子.txt");
//使用Newtonsoft反序列化
var model = JsonConvert.DeserializeObject<TestJson>(json);
其實這個套路大部分人也都懂,但我知道的也有一些在線解析工具,但貌似遇到特別復雜的,不好整,這個工具是我見過的里面比較簡單易用。看看解析的數據,結構化后,非常清晰,自己想要那個數據,自己去屬性依次獲取就好了。

3.就這么完了?No,沒那么簡單
工具能解決的問題一般不是全部,能解決8成就很不錯了,雖然這個工具剛開始就解決了很多問題,但隨着JSON的復雜化,也碰到了一些坑,看看如何填坑。現在已經是填坑專業戶了。
3.1 為什么要使用嵌套類(nested classes)
為什么在對於復雜的類型我選擇使用嵌套類,原因很簡單,結構更清晰,否則生成的cs文件里面一堆類,都搞不清楚那個是最外面的,對這種需求,適當的代碼冗余就無所謂了,我需要的是快速的拿到自己想要的數據。何況是自動生成的。當然對於簡單的類型,不使用嵌套類也是可以的,看個人習慣吧。
3.2 解析會碰到類型名稱為數字的字段
雖然比較奇葩,但的確是遇到了,獲取的JSON字符串里面的字段名稱為數字,怎么破?鬼知道人家這么拼出來的,反正是為了采集,還得有解葯才行。既然原始的是數字,那就把原始的給改了,我們把屬性是數字的地方,都給加一個默認值,然后生成實體類,不就可以了,不過想在這么一堆亂七八糟的東西里面把所有的數字屬性加個默認值,也不容易啊,還好有萬能的正則表達式。
我們寫一個簡單的正則表達式匹配方法,把數字屬性統一替換為前面加個默認的字母A,代碼如下:
public static string GetNewJson(String json)
{
Regex reg = new Regex("\"([^\"]d*)\":"); //注意里面的引號 要用雙引號表示,而不是用反斜杠
MatchEvaluator matchEval = new MatchEvaluator(ReplaceStar);
return reg.Replace(json, matchEval);
}
static string ReplaceStar(Match match)
{
string str = match.Value.Replace("\"", "").Replace(":", "");
return "\"A" + str + "\":";
}
3.3 相同結構的,但解析為不同的類名
很多時候某個屬性下面有多個相同結構的對象,但是會根據名稱解析為不同的類,結構基本一直,在獲取對象數據的時候,又不是數組對象,循環還不好搞,那怎么破?
手動建一個中間類,結構和他們一樣,使用TinyMaper,這里有文章介紹,將這些類型默認都映射到這個中間類中,然后其他各個相同結構對象的解析只需要寫一份代碼就OK了。看看下面的方法:
public class LineRato
{
public string LgMailNo;
public string CreateTime;
public string EventTime;
public string EventAddress;
public string NodeType;
public string Timeout;
/// <summary>將其他結構相同的類轉換為中間類</summary>
public static LineRato GetLine<T>(T model)
{
TinyMapper.Bind<T, LineRato>();
return TinyMapper.Map<LineRato>(model);
}
}
3.4 空值導致實體類字段缺失
某些時候我們在第一次獲取JSON值的時候,由於某些值是空的,導致實際的JSON值里面沒包括該字段,所以在生成的時候實體類里面肯定沒有這個字段,而實際多次后發現某些情況下該值又不為空,會導致解析失敗,這個時候怎么破?
沒辦法破了,為了省事,看看是那里缺少字段,手動加上吧,就一行代碼的事情。
總之,在解決了80%問題后,剩下的方法比問題多多了,大家各顯神通吧。這里只是吧自己的解決過程寫下來,最快的解決問題,OK!其他費腦細胞的事情還是給有精力的人!
4.資源
本文代碼:JsonClassTest.rar
