1. 程式人生 > >用原始方法解析複雜字串,json一定要用JsonMapper麼?

用原始方法解析複雜字串,json一定要用JsonMapper麼?

    經常採集資料,肯定會碰到解析字串,包括整個頁面的html,或者json以及一些不標準的json格式。。。

    以前用json序列化,有時候需要實體類,有的時候沒有,比較麻煩,聽說可以用JsonMapper,解析為字典格式。不過沒用過,習慣了用最原始的方法來解析字串,所以這裡分享幾個解析的案例。也許會有點作用。

    解析字串最常用的應該是Splite和Replace了。分割,然後替換一些引號之類的。最後組合。特別是採集的時候,經常會把html頁面中某一段要提取出來,可能很多人用正則表示式,可是不會啊,也不願意去學。那隻好用這些原始的方法了,時間久了,也積累一些經驗或者函式。看看幾個例子。

1.不規則非json字串

    先看看這個例子,字串是連在一起,沒有換行的,為了方便觀察,換行了,程式是原始在一起的:

[11101630,1532,14,'0','0',3,'2015,4,23,16,05,48','4',1,2,0,0],
[11101631,1532,14,'0','0',3,'2015,4,23,16,09,48','0',,,0,0],
[11101632,1532,14,'0','0',3,'2015,4,23,16,03,10','1',2,2,0,0]

    先來分析一下這個字串的特點,才能找到思路哦:

1.每一組資料都是在[]括號對中,每一組資料用,號分割,所以最終要形成一個數組來訪問哦。

2.每一組的資料基本都是用 , 號分割,字串型別還有單引號 ;

3.第7個數組是一個整體,也使用,號分割,整體是字串有引號;

4.第2組資料有空值,直接用,號分割,所以splite的時候不能去掉空值,否則陣列長度不一樣,定位就亂了。

    既然分析都完了,那思路呢?

1.組直接分割使用  ], 標記,然後每一組要Repalce掉 [  和 ] 。主要是最前和最後;

2.組內分割,使用  ,號標記分割,出來之前要把單引號給 替換掉 ;不然也是作為字串,引號也包括進去了;

3.至於那個 陣列 的處理,不能過於想複雜,分割之後,直接在最後增加1個元素,將固定位置7-12的組合起來;這樣也許方便點;

4.由於空值有佔位,所以每一組的長度是固定的。所以處理的時候直接根據自己想要的位置來組合。

    下面看看程式碼了,C#版本,相對與一行程式碼,仔細看,Linq很是一個神器,真的是神奇。。。說多了都是淚,為啥就沒早點學呢:

String str = @"[11101630,1532,14,'0','0',3,'2015,4,23,16,05,48','4',1,2,0,0],[11101631,1532,14,'0','0',3,'2015,4,23,16,09,48','0',,,0,0],[11101632,1532,14,'0','0',3,'2015,4,23,16,03,10','1',2,2,0,0]";

var result = str.Split(new string[] { "]," }, StringSplitOptions.None)  //先整體分割組
				.Select(n => n.Replace("[", "")  //以下是組內分割,並去掉其他干擾字元
				.Replace("]", "")
				.Replace("\'", "")
				.Split(',').ToList())
				.Select(n =>     //對中間一個整體單獨提取,進行組合,單獨增加一個元素
				{
					n.Add(String.Format("{0},{1},{2},{3},{4},{5}", n[6], n[7], n[8], n[9], n[10], n[11]));return n;
				}).ToList();

看看結果怎麼樣:

blob.png

2.鍵值對字串分割函式

  由於json資料格式都是鍵值對字串,所以這裡特意分享一個經常用到的分割函式,不用Json元件,那就用簡單的方法做一個。這個函式來源於Newlife.Core,是X元件的重要部分。原始碼部分不過多解釋,就是按規則將鍵值對直接分割保持在字典中,使用方法大家可以自己實驗一下,或者參考下面的案例,都有用到這個方法。程式碼如下,為了方便使用,寫成了擴充套件方法:

public static class StringHelper
{
	/// <summary>拆分字串成為名值字典</summary>
	/// <param name="str">要分割字串的</param>
	/// <param name="nameValueSeparator">鍵值對的分隔符</param>
	/// <param name="separators">分割字元</param>
	/// <returns>鍵值對字典</returns>
	public static IDictionary<String, String> SplitAsDictionary(this String str, String nameValueSeparator = "=", params String[] separators)
	{
		var dic = new Dictionary<String, String>();
		if (String.IsNullOrWhiteSpace(str)) return dic;

		if (String.IsNullOrEmpty(nameValueSeparator)) nameValueSeparator = "=";
		if (separators == null || separators.Length < 1) separators = new String[] { ",", ";" };

		String[] ss = str.Split(separators, StringSplitOptions.RemoveEmptyEntries);
		if (ss == null || ss.Length < 1) return null;

		foreach (var item in ss)
		{
			Int32 p = item.IndexOf(nameValueSeparator);
			// 在前後都不行
			if (p <= 0 || p >= item.Length - 1) continue;

			String key = item.Substring(0, p).Trim();
			dic[key] = item.Substring(p + nameValueSeparator.Length).Trim();
		}

		return dic;
	}
}

  上面預設的鍵值對分割符號為 = 號,根據實際情況進行修改,json格式裡面一般是:冒號比較多。

3.複雜Json格式的字串

    上面的例子比較簡單,這次看一個稍微複雜點的,雖然可能用JsonMapper可以很輕易做到,但試一下最原始的方法吧。還是按照上面的思路,先分析字串的特點:字串是連在一起,沒有換行的,為了方便觀察,換行了,程式是原始在一起的:

{1074:['墨聯','墨聯','MEX D1','#098000','98'],
 2100:['美乙','美乙','USL D2','#E89B10','98'],
 1024:['阿甲','阿甲','ARG','#00CCFF','98'],
 1052:['哥倫甲','哥倫甲','COLCMA','#888500','98'],
 1028:['K聯賽','K聯賽','KORL','#F75000','98'],
 1297:['球會友誼','球會友誼','CF','#5691D8','98'],
 2085:['奧女甲','奧女甲','AFB','#D86220','97']}

還是先分析特點,這個格式應該是json類似的了,比較規則:

  1. 組與之間是使用 , 號分割;前後有{}括號對;觀察前後可以使用 ], 字串將組分開;

  2. 鍵 是整數,鍵值是通過 : 號分割;

  3. 值是一個數組,有5個元素,通過 , 號分割

  4. 都有單引號,需要過濾掉;其他沒有特殊情況;

程式碼解決過程:

string text = @"{1074:['墨聯','墨聯','MEX D1','#098000','98'],2100:['美乙','美乙','USL D2','#E89B10','98'],1024:['阿甲','阿甲','ARG','#00CCFF','98'],1052:['哥倫甲','哥倫甲','COLCMA','#888500','98'],1028:['K聯賽','K聯賽','KORL','#F75000','98'],1297:['球會友誼','球會友誼','CF','#5691D8','98'],2085:['奧女甲','奧女甲','AFB','#D86220','97']}";
var dic = text.Replace("\'", "").Split(new String[]{"],"}, StringSplitOptions.None) //先組分割
			  .Select(n => n.Replace("{", "").Replace("}", "") //將組裡面的干擾字元過濾掉
							.Replace("[", "").Replace("]", "")
			  .SplitAsDictionary(":", "\"") //鍵值對處理,冒號分隔符
			  .ToDictionary(t => t.Key, t => t.Value.Split(',')//值再次進行分割,形成陣列
			  )).ToArray();

看看結果如何:

blob.png

4.標準的json格式

    在實際的採集過,可能會碰到直接url,返回的就是json格式,比較標準。這裡舉個例子,如下面這個頁面連結:

點選開後,是這個樣子:

blob.png

這個應該夠複雜了,我們分析一下,篇幅較大,原始碼對照連結:

  1. 每一大組資料,是用,號分割;整體也是前後大括號對{},有4個大類,鍵分佈是:IndBodans,IndEvenGoals,IndGoalss,IndHalfFulls。

  2. 每一組的子類中,包括的都是同一個型別的資料,每一個子資料組都有N多個小的鍵值對,如MatchId,CorpId等等,使用},可以分割

    分析完成之後如何解決,思路是類似的,先整體分割,使用},進行,然後每一個之類作為鍵,對值再次進行分割。。。形成字典列表。其中的引號也是需要過濾的,至於數值型別,實際用到那個的時候,都是根據key去找,再進行Convert轉換就可以了。看看原始碼:

var dicList = doc.Split("{\"IndBodans\":[", "],\"IndEvenGoals\":[", //大類分割
						"],\"IndGoalss\":[", "],\"IndHalfFulls\":[", "]}")
			.Select(n => n.Replace("\"", "").Split("},{")//對每個大類處理,先過濾,再分割為子類
			   .Select(k => k.Replace("{", "").Replace("}", "")//對子類過濾
		                  .SplitAsDictionary(":", ","))//提取子類的鍵值對
				  .ToArray()
			).ToList();//列表

看看解析的結果如何:

blob.png

注意,有元素是空值的,可以不用管。至於那幾個鍵值對陣列,最終屬於哪一個大類?雖然沒有直接標記出來,但是這個問題隨便加一個判斷就可以了,因為每一個類別的鍵名稱是不一樣的,看看是否包括對應的鍵就可以確定類別。

5.總結

    雖然過程很簡單,也許有更簡單的辦好,直接和實體類對映,json反序列化更方便,但有時候沒有實體類,也挺麻煩。特別是這種變態複雜的,jsonmap直接處理不知道行不行。總之本文的目的是儘可能使用簡單原始的方法來解決問題,也是一個思路。雖然有時候我很懶,喜歡用開源元件,但有的時候一旦用上原始的了,也不喜歡改了。

    字串分析處理的過程雖然繁瑣,但基本都是比較簡單的,細緻一點,都不是事。

  最後把這個測試的原始碼發上來,大家別忘了點贊哦。。。

相關推薦

原始方法解析複雜字串json一定JsonMapper

    經常採集資料,肯定會碰到解析字串,包括整個頁面的html,或者json以及一些不標準的json格式。。。     以前用json序列化,有時候需要實體類,有的時候沒有,比較麻煩,聽說可以用JsonMapper,解析為字典格式。不過沒用過,習慣了用最原始的方法來解析字串,所以這裡分享幾個解析的案例。也

原始方法解析復雜字符串json一定JsonMapper麽?

之間 正則表達式 isn ces plain cli shu 如何解決 clist 轉自數據之巔原文用原始方法解析復雜字符串,json一定要用JsonMapper麽? 閱讀目錄 1.不規則非json字符串 2.鍵值對字符串分割函數 3.復雜Json格式

js 將json字串轉換為json物件的方法解析(簡單處理JSON語法格式校驗問題)

js 將json字串轉換為json物件的方法解析 將json字串轉換為json物件的方法。在資料傳輸過程中,json是以文字,即字串的形式傳遞的,而JS操作的是JSON物件,所以,JSON物件和JSON字串之間的相互轉換是關鍵 例如: JSON字串: var str1 = ‘{

JavaPOI讀取解析Excel時遇到科學計數法的解決方法

在匯入excel2003或者2007的時候難免會遇到某些單元格雖然是文字數字,但是使用java的poi來解析時會出現科學計算形式,下面我們看怎麼去掉這種格式,以文字來顯示: 1、導包 <!-- https://mvnrepository.com/artifact/org.apa

angular6解析模板字串$compile服務在angular6中的實現方法

angular6解析動態字串模板 依賴: Compiler服務 viewContanierRef服務 步驟: 建立指令,並通過指令接受字串 接受字串,並通過此字串動態建立元件及模組 compiler服務解析元件和模組 通過將解析出來的元件新增到dom容器中

微信小程式大坑:encode後的JSON字串JSON.parse解析失敗

今天,遇到微信 JSON 解析的一個大坑。 網上找了好久,沒有人記錄過相同坑,所以寫下來吧。 跨頁面跳轉,想傳遞一個物件。於是先將物件,用 infoStr=JSON.stringify(object

JSON陣列json字串JSON物件陣列的區別與基本操作整理

JSON陣列,json字串,JSON物件,陣列的區別與基本操作整理 json字串 var objString = '{"a":"1","b":"2","c":"3"}'; json物件       var object

指標方法編寫一個程式輸入3個整數將它們按由小到大的順序輸出

#include <stdio.h> void swap(int *pa,int *pb) { int temp; temp = *pa; *pa = *pb; *pb = temp; } void main() { int

java使用org.json解析josn字串json檔案

準備org.json.jar 一、最近做專案需要操作json,趁著次機會就好好總結一下。本次使用的是org.json提供的jar包,下載地址為mvnrepository(jar包倉庫,開發所需的jar包都可以在上面下載)。 二、在eclipse上匯入外部jar檔案,方法:

java dom4j解析複雜xml成json

import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.dom4j.Document; import org.dom4j.Elemen

java關於使用subList方法擷取的字串放入redis快取的相關問題及解決方法

    在前幾天做專案的時候,會對其他專案通過阿里雲發來的訊息中的某個List型別的欄位進行擷取,並將擷取後的結果存入redis中。但是在專案執行起來的時候,獲取redis中該欄位的內容會出現錯誤,錯誤提示如下: (error) WRONGTYPE Operation a

Android利用Gson庫解析複雜結構的JSON資料

最近在應用Face++進行人臉識別開發時,經常需要解析Face++返回的結構複雜的JSON資料,於是便決定應用Google開發的Gson庫來減輕工作量。 首先給大家看一個比較複雜的JSON資料: {"face":[{"attribute":{"age":{"

json字串json物件java物件互相轉換

1.把JSON字串轉換為JAVA 物件  JSONObject jsonobject = JSONObject.fromObject(jsonStr);  User user= (User)JSONObject.toBean(object,User.class);2. 把java物件轉換成json物件,並轉化

markdown.js解析markdown時設定圖片大小

markdown設定圖片大小 打算在網頁上顯示.md文件,發現可以用markdown.js實現,具體看這篇文章: 實現網頁客戶端實時自動解析Markdown為HTML內容 可是發現不能調整圖片大小,好像markdown本身就沒有考慮這個問題。要麼找

explain來解析sql語句然後建立正確的索引

用explain mysql中來解析sql語句是一個非常好用的工具,它可以檢視你的sql語句的執行是直接全部掃描,還是經過索引優化的。用它來分析sql語句也可以避免一些無用的索引。下面來看一個例子: 用sql來查詢表中是否有匹配的a或者b(一共180w條記錄)第一版: 一條

後端java解析複雜巢狀json

其實不是很複雜 百度翻譯傳過來的json資料:{"from":"zh","to":"en","trans_result":[{"src":"高度600米","dst":"Height 600 meters"}]} 現在要取出dst對應的值:Height 600 meter

儘量簡單方法處理複雜問題

在大學裡,用複雜的邏輯去解決問題。會讓老師覺得這個學生很聰明,很有能力。 而在公司這樣做,只會得到各種鄙視。 下面說說採用複雜邏輯解決問題的弊處: 1.可控性差。 當你的演算法複雜了,很多邊界問題和異常情況是很難考慮周到的,最後你會被各種段錯誤、踩記憶體、異常結果搞的焦頭

關於在JSP頁面中為什麽一定${pageContext.request.contextPath}來獲取項目路徑而不能${request.contextPath}?

html 輸出 獲取項目路徑 session PE ade ror ESS val 這裏的疑問在於pageContext和request都是JSP中的內置對象之一,為什麽不直接用${request.contextPath}來獲取項目路徑?出現