、為什么利用json傳輸數(shù)據(jù)?
xml數(shù)據(jù)生成過于復雜
xml數(shù)據(jù)解析過于復雜
2、關于json介紹
對象是屬性的無序集合
在js中, 可以使用{}模擬這個集合
語法:
var json={屬性:屬性值,屬性:屬性值}
注意:屬性可加可不加引號(包括單引號和雙引號)
3、用json個表示具體的信息
(1)表示一個人的信息
var person={name:'zhangsan',age:30};
alert(person.name+person.age); //顯示張三30
(2)表示多個人的信息
var data=[{
name:'zhangsan',
age:30
},{
name:'lisi',
age:18
},{
name:'wangwu',
age:25
}];
for(var i=0;i<data.length;i++){
document.write(data[i].name+data[i].age);
document.write('<hr>');
}
4、在php中如何使用json
json_encode(); //json編碼
json_decode(); //json解碼
mixed json_decode ( string $json [, bool $assoc=false] )
json 待解碼的 json string 格式的字符串。
assoc 當該參數(shù)為 TRUE 時,將返回 array 而非 object 。
默認返回一個對象
$obj=json_decode($str);
加上參數(shù)true表示數(shù)組
$arr=json_decode($str,true);
生成json字符串
json表示大量數(shù)據(jù), 在php中表示多個、大量的數(shù)據(jù)可以數(shù)組、對象來表示
也就是說, 在php, 如果想生成json字符串, 必須從數(shù)組、對象上生成。
復合數(shù)據(jù)類型:數(shù)組、對象
從數(shù)組中生成json字符串
$row=array('name'=>'lisi','age'=>30);
echo json_encode($row);
從對象中生成json字符串
class Person{
public $name='zhangsan';
public $age=20;
}
$p1=new Person();
$str=json_encode($p1);
關于json保存中文的問題
目前, json只支持utf-8, 如果想保存中文, 必須進行轉(zhuǎn)碼
$arr=array('name'=>'張三','age'=>30);
$arr['name']=iconv('gb2312','utf-8',$arr['name']);
echo json_encode($arr);
5、在javascript中json語法:
var str=xmlHttp.responseText;
var json=eval("("+ str +")"); 返回是json對象
var json=eval(str); 返回是json數(shù)組對象
理解:eval()函數(shù)可以將php中的json字符串轉(zhuǎn)換為javascript可執(zhí)行的json對象(包括數(shù)組對象)
6、案例:
php代碼:
$row:一維數(shù)組 生成一個json格式的字符串
$data:二維數(shù)組 生成一個json數(shù)組格式的字符串
<?php
$row=array('username'=>'lisi','password'=>'222222');
echo json_encode($row); 輸出:{"username":"lisi","password":"222222"}
/*
$data=array(
array('name'=>'zhangsan','age'=>18),
array('name'=>'lisi','age'=>30)
);
echo json_encode($data);//輸出:[{"name":"zhangsan","age":18},{"name":"lisi","age":30}]
*/
?>
HTML代碼:
<script language="javascript" src="public.js"></script>
<script>
var xhr=createxhr();
xhr.open('post','demo05.php');
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
var value=xhr.responseText; //返回的是字符串
//(1)
var json=eval('('+value+')'); //返回是json對象
alert(json.username+json.password);
//(2)
//var json=eval(value); //返回是json數(shù)組對象
//alert(json[0].name+json[0].age);
}
};
xhr.send(null);
</script>
理解:
var json=eval('('+value+')'); 主要是針對關聯(lián)數(shù)組
返回:"{name:'zhangsan',age:18}"
訪問方式:json.username+json.password
var json=eval(value); 主要是針對索引數(shù)組
返回:"[{name:'zhangsan',age:18},{name:'lisi',age:20}]"
訪問方式:json[0].name+json[0].age
注意:索引數(shù)組的解析也可以采用 var json=eval(value);
查詢數(shù)據(jù)表中所有數(shù)據(jù)并生成json字符串返回
php代碼:
<?php
//查詢goods表中所有數(shù)據(jù)并返回
$sql="select name,price from goods order by id desc";
mysql_connect('localhost','root','111111');
mysql_select_db('shop');
mysql_query('set names gb2312');
$result=mysql_query($sql); //發(fā)送sql語句
$num=mysql_num_rows($result); //總行數(shù)
$data=array();
for($i=0;$i<$num;$i++){
$row=mysql_fetch_assoc($result);
$row['name']=iconv('gb2312','utf-8',$row['name']);
$data[]=$row;
}
mysql_close();
echo json_encode($data);
PHP代碼:
笑的Night King
星期四的時候,我遇到了一個文件上傳的問題,與以往不同的是,這一次上傳的是多個文件,而且涉及到了久違的javascript代碼。(久違是因為前后端分離的趨勢,好久沒有碰過JS)
雖然最后實現(xiàn)的差強人意,不過也算是完成了功能,接下來就把我發(fā)現(xiàn)的一些問題和總結記錄一下。
<form id="tempFile" method="post" enctype="multipart/form-data"> <!-- 指令模板文件上傳 --> <div style="text-align: center;"> <div class="clearfix" style="width:400px;margin:0 auto;"> <input id="templatesFile" type="file" multiple="multiple" /> </div> </div> </form>
上述代碼可以看到,只是一個簡單的 form表單,里面嵌套了一個 input 輸入框,這個 input 輸入框的 type 類型是file,值得注意的是,如果是允許上傳多個文件,那么input輸入框必須添加multiple="multiple" 屬性。
這里要說明一點,由于使用 submit 按鈕提交 form表單會造成頁面刷新,因此,現(xiàn)在一般都采用按鈕與 form 表單分離的方式,使用 AJAX來異步上傳數(shù)據(jù)。 如下所示:
<button class="btn btn-default" onclick="sendTemplates();" title="upload"> 上傳模板文件 </button>
/** * 上傳模板文件 * @returns */ function sendTemplates() { // 需要上傳的文件 // var templates=document.getElementById("templatesFile").files; var templates=$("#templatesFile")[0].files; if (templates.length > 2) { alert("上傳失敗,一次最多兩個文件!"); return; } var formdata=new FormData(); for (var i=0 ; i < templates.length ; i++) { formdata.append("temp" + i, templates[i]); } $.ajax({ url : "/manager/uploadTemplates", type : "POST", data : formdata, processData : false, contentType : false, success : function(resultMap) { if (resultMap.code=="OK") { alert("上傳成功!"); } else if (resultMap.code=="FAIL") { alert(resultMap.msg); } }, error : function(e) { alert("服務器異常"); } }); }
代碼已經(jīng)保留了關鍵的代碼部分,剔除了一些無關緊要的操作。
@RequestMapping(value="/uploadTemplates", method=RequestMethod.POST) @ResponseBody public Map<String, Object> uploadTemplates(HttpServletRequest request) { MultipartHttpServletRequest multipartRequest=(MultipartHttpServletRequest) request; List<MultipartFile> templatesList=new ArrayList<>(); for (int i=0 ; i < 2 ; i++) { templatesList.addAll(multipartRequest.getFiles("temp" + i)); } MultipartFile[] templates=new MultipartFile[templatesList.size()]; templatesList.toArray(templates); Map<String, Object> result=templateService.uploadTemplates(templates); return result; }
看到上面的代碼,我不得不說,真的和 shi 一樣。不過目前我還沒找到很好的辦法。
好在 for 循環(huán)的 getFiles(...) 如果取不到值的話,就會返回一個空的 List 不會直接拋出異常。
以上就是所有關鍵的代碼部分,下面來說一說調(diào)試過程中我使用過的幾種方法,以及覺得很坑的地方。
回看js 部分的代碼,相信你已經(jīng)注意到了:
var templates=$("#templatesFile")[0].files;
而FileList 并不是一個數(shù)組。如果希望將它轉(zhuǎn)化成一個數(shù)組,可以使用 Array.from(FileList)
不過不論是 FileList還是數(shù)組,都不是重點,重點是$("#templatesFile")[0] 一定要加上后面的這個 [0] 。而如果使用document.getElementById("...")就不必加 [0]。 這是因為 files 屬性是原生js屬性,而不是jQuery屬性,因此需要通過這個 [0] 將jQuery對象轉(zhuǎn)化為 js對象,才能通過 .files 獲得這個FileList !
說實話,前面的 js 與 java部分的代碼實在是迫不得已,不過依然沒有找到恰當合適的方法。
這個問題困擾了我整整一天的時間,從星期四的下午開始研究一直到第二天星期五的上午才勉強以上面的代碼跑通功能。
之前做過上傳單個文件的功能。那天我樂觀的以為,只要前端能夠獲取到 files 數(shù)組,然后后端的接口使用 MultipartFile[] 來接收就可以大功告成了!像這樣:
@RequestMapping(value="/uploadTemplates", method=RequestMethod.POST) @ResponseBody public String uploadTemplates(MultipartFile[] templates) { // ...some codes }
但是前端的代碼我試過N種方法依然無法成功接收到這個文件數(shù)組!不論是這樣:
還是這樣:
亦或是將數(shù)組轉(zhuǎn)化成String,然后后臺用String接收:
都 完!全!沒!用!
明明以前傳其他類型的參數(shù)是OK的啊!這到底是為什么?
于是看到了 FormData 的解決方案。但是事情依然并!不!簡!單!
一開始我的思路是封裝一個FormData對象,然后把文件數(shù)組整體放入到一個value中,并且指定一個key ,這樣后臺通過 getFiles() 方法就可以獲得整個文件列表了。
然鵝,并無卵用!
在網(wǎng)上找了下原因,看到了一些別人的代碼,全都是每一個key放一個文件!原因是:
簡單的說, String、Blob、File可以被FormData傳輸(注意這里是單個File類型的文件),如果是其他類型,則會被轉(zhuǎn)化成字符串,然而,對于FileList又會是怎樣的情況呢?我找到了下面這句話:
Using the FormData API is the simplest and fastest, but has the
disadvantage that data collected can not be stringified.
翻譯過來就是,使用FormData最簡單,也最高效,但是有一個缺點是,數(shù)據(jù)集合(比如List或者數(shù)組)無法被序列化為字符串。
簡直就像是在耍人一樣!我真的崩潰了!
也就是說,我必須將文件列表(或者數(shù)組)中的每一個文件取出來,分別給每一個文件指定一個Key才能成功的通過formdata傳輸?shù)胶笈_并接收。
所以才有了這樣的代碼:
// JS var formdata=new FormData(); for (var i=0 ; i < templates.length ; i++) { formdata.append("temp" + i, templates[i]); }
和這樣的代碼:
// java controller public Map<String, Object> uploadTemplates(HttpServletRequest request) { MultipartHttpServletRequest multipartRequest=(MultipartHttpServletRequest) request; List<MultipartFile> templatesList=new ArrayList<>(); for (int i=0 ; i < 2 ; i++) { templatesList.addAll(multipartRequest.getFiles("temp" + i)); } // some other codes... }
到目前為止,還沒有找到更加簡潔和高效的代碼,有哪位全棧的哥們可以告訴我嗎?
歡迎評論區(qū)留言哦!非常感謝!
---歡迎關注【Java圣斗士】,我是你們的小可愛(?ω?) Morty---
---專注IT職場經(jīng)驗、IT技術分享的靈魂寫手---
---每天帶你領略IT的魅力---
---期待與您陪伴!---
前一直是用form表單,通過設置enctype="multipart/form-data"然后submit來上傳文件的,但是在通過ajax方式跟后端進行數(shù)據(jù)交互時,這個方法就有點麻煩來,所以找到了ajax來上傳文件的方法了。
下面是一個演示:
html文件
其中FormData是XMLHttpRequest Level 2的一個對象,有些瀏覽器可能不支持(感覺都支持的差不多了)。processData設置為false,網(wǎng)上說是data值是一個對象了,不需要對數(shù)據(jù)再做處理了,contentType設置為false,是不要設置Content-Type請求頭了。請求類型還是post方式提交。
php代碼
服務端php代碼沒做多少事情,就是把$_POST和$_FILES打印出來,同時通過move_uploaded_file方法把文件上傳到當前目錄。
上傳成功的返回值
上傳成功的返回值,利用console.log()函數(shù)打印出來了,可以看到,服務端中只用$_FILES有值,$_POST為空。
文件成功上傳成功
上圖顯示文件上傳到當前目錄。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。