LitJson使用中需要注意的一些問題
使用C#做Untiy開發時,有解析Json的需求,選擇使用了LitJson這個庫,因為之前我們是使用lua的,這個庫會將Json解析后保存為JsonData,這個JsonData和lua的table使用上有點類似,但有些問題要注意。
- 取值時要先檢測key是否存在
lua的table可以使用 some_table.key或 some_table[‘key’] 來取值,key不存在則返回nil,但是JsonData中如果key不存在,則 some_data[“key”] 會拋出異常,所以在取值前必須要先用Contains檢測下,並且由於JsonData同時實現了IDictionary和IList接口,並且都是實現為顯示接口成員,所以還要顯示的指定是IDictionary的Contains:
int intValue = 0; if(((IDictionary)some_data).Contains("value")){ intValue = (int)responseData["value"]; }
-
取值后要轉型
和lua不同,c#是強類型的,從JsonData中取出的值必須要轉型才能賦值,如上面的代碼,使用(int)強轉。當然如果value本身就是JsonData則可直接賦值給JsonData類型的變量。 -
整形值轉型到long可能拋出異常
如果json文本中含有數字,LitJson會優先識別為int32,僅當Int32.TryParse失敗時才識別為int64,這其實也是合理的。問題是想把某個整形值轉換為Long時,很可能拋出異常,例如: long value = (long)data[“key”]; 如果key對應的值是1000這樣,這個轉換就會拋出異常。這是因為LitJson沒有考慮到int32到int64的轉換。我修改了一下Int64的轉換函數就可以了,修改后的函數如下:
public static explicit operator Int64 (JsonData data) { if (data.type != JsonType.Long && data.type != JsonType.Int) throw new InvalidCastException ( "Instance of JsonData doesn't hold an int"); return (data.type == JsonType.Long)?data.inst_long : data.inst_int; }
-
使用IDictionary和IList接口的方法時要先轉型到相應接口
如上面所說,JsonData同時實現了IDictionary和IList接口,並且都是實現為顯示接口成員,這兩個接口有一些方法是同名的,比如Remove方法,一個是void IList.Remove (object value),另一個是void IDictionary.Remove (object key)。盡管一個JsonData對象不可能即是數組又是鍵值對,但是直接調用Remove的時候還是要轉換到相應的接口。這個和lua的table相比還是不太方便。當然了,即便不是同名的接口,由於都實現為顯示接口成員了,還是必須轉型到接口才能調用。 -
不支持取值轉型到ulong等類型
JsonData取值時的轉型,只支持幾種有限的類型,沒有ulong等無符號類型的轉換函數。如果想把取得的值轉型到一個ulong,例如:
ulong value; value = (ulong)some_data["key"];
結果是會調用到Double的轉型函數,如果key對應的value不是一個double則會產生InvalidCastException。
- 要解析的string里面不能包含0值
我們遇到的一個bug是,服務端傳過來的Json字符串末尾人為的加了一個’/0’,結果JsonMapper.ToObject就掛了。LitJson可能認為一個c#字符串中不應該包含’/0’,所以他沒有處理這種情況,對於不能處理的字符他拋出了一個異常。盡管人為加’/0’是沒必要的,但是這顯然也是LitJson實現時考慮不周全。