1. 程式人生 > >由數據庫某字段存數組引發的json_encode/serialize思考

由數據庫某字段存數組引發的json_encode/serialize思考

target 不同的 quest 超過 spa 散列 集合 支持 傳輸

導火索場景:

  • 原來:mysql中 result表 img字段原存儲字符串,內容為某圖片鏈接;
  • 現在:該字段需要存儲多張圖片鏈接,1-3個元素行程的數組;

google得到的普遍建議有兩種: https://stackoverflow.com/questions/3413291/how-to-store-an-array-into-mysql

  • 建議一:根據具體場景構建多張表,通過主鍵外鍵形成關聯。

  優點:支持針對數組中某個字段的查詢等;缺點:需要結合具體場景

  • 建議二:序列化數組,php提供內置方法支持序列化與反序列化(serialize / unserialize)(開發完後發現仍存在另一種序列化方式json_encode / json_decode

  優點:方便實現;缺點:數組被看作整體,不支持對單個元素的操作;

不存在針對單個圖片鏈接的查詢等操作,選擇建議二。

問題:接口postman img參數一欄值寫 [xxx,xxx]序列化後入庫,獲取時反序列化預期返回數組的出參 [xxx,xxx],實則返回string類型的 "[xxx,xxx]"

排查過程:在php中gettype查看數據類型,入參實則為string類型,json_decode後才為array類型

原因:postman img參數一欄值寫 [xxx,xxx],此時其實為string類型,json類型的數組。

後續一:對json類型的了解一直過於膚淺,乘此機會學習之,相關資料讓我茅塞頓開,總結分享如下。

1. json可以理解為符合一定書寫格式的字符串,實質仍是string;

2. json具體的格式規則可以總結為4句話

技術分享

3. json只接受utf-8編碼的字符,所以json_encode()的參數必須是utf-8編碼,否則會得到空字符或者null,

起初看了json的文檔,就是被這些規則,[],{}混亂了,但看到下面一段話就通了。來源(阮一峰:數據類型和json格式)

它說,從結構上看,所有的數據(data)最終都可以分解成三種類型

第一種類型是標量(scalar),也就是一個單獨的字符串(string)或數字(numbers),比如"北京"這個單獨的詞。

第二種類型是序列(sequence),也就是若幹個相關的數據按照一定順序並列在一起,又叫做數組(array)或列表(List)

,比如"北京,上海"。

第三種類型是映射(mapping),也就是一個名/值對(Name/value),即數據有一個名稱,還有一個與之相對應的值,這又稱作散列(hash)或字典(dictionary),比如"首都:北京"。

現在,任何的數據類型都可以歸並到以上三類中。數組表示有序數據的集合,而對象表示無序數據的集合。如果數據的順序很重要,就用數組,否則就用對象

而我的[],{}混亂也解決了,[]對應的為序列,也可稱為索引數組;{}對應的為映射,也可稱為關聯數組。來源:阮一峰:在PHP語言中使用json

json_encode和json_decode在第二三種類型上的操作則可理解為string類型和映射或序列之間的轉換;對於標量來說,則是進行編碼轉義(只搜到底層會unicode,具體未找到?

//序列,索引數組
$arr = Array(‘one‘, ‘two‘, ‘three‘);
echo json_encode($arr);        //["one","two","three"] 

//映射,關聯數組
$arr = Array(‘1‘=>‘one‘, ‘2‘=>‘two‘, ‘3‘=>‘three‘);
echo json_encode($arr);       // {"1":"one","2":"two","3":"three"} 

//特別說明,映射的decode
$json = ‘{"a":1,"b":2,"c":3,"d":4,"e":5}‘;
var_dump(json_decode($json));     //默認生成stdClass對象
object(stdClass)#1 (5) {  
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
  
  }
var_dump(json_decode($json,true));    //加參數true,指定生成關聯數組
array(5) {  
     ["a"] => int(1)
     ["b"] => int(2)
     ["c"] => int(3)
     ["d"] => int(4)
     ["e"] => int(5)  
  }

後續二:序列化

何時需要序列化?

復雜數據結構在php腳本執行過程在內存中存儲,但不可用於直接傳輸/存儲入庫等。

序列化的實質是什麽?

數據結構存儲會有對應的數據結構,序列化實則可以理解為降維的過程。

json_encode/serialize的區別?

都是序列化生成字符串的過程,采用不同的規則。自我理解,serialize是php 3.05開始支持,生成字符串更為緊湊,json_encode是PHP 5.2之後支持,可讀性更好。

更新區別:

JSON vs. Serialized Array in database [closed]

Preferred method to store PHP arrays (json_encode vs serialize)

基本評價是,json的易讀性更好、速度更快、序列化後存儲空間更小。

只在以下幾種情況不選擇json:

1. 使用php版本過低,不支持;

2. 需要存儲的復雜結構元素過多,超過127個元素,json將返回錯誤;

3. 需要保留類名等信息

由數據庫某字段存數組引發的json_encode/serialize思考