、为什么利用json传输数据?
xml数据生成过于复杂
xml数据解析过于复杂
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 当该参数为 TRUE 时,将返回 array 而非 object 。
默认返回一个对象
$obj=json_decode($str);
加上参数true表示数组
$arr=json_decode($str,true);
生成json字符串
json表示大量数据, 在php中表示多个、大量的数据可以数组、对象来表示
也就是说, 在php, 如果想生成json字符串, 必须从数组、对象上生成。
复合数据类型:数组、对象
从数组中生成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, 如果想保存中文, 必须进行转码
$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数组对象
理解:eval()函数可以将php中的json字符串转换为javascript可执行的json对象(包括数组对象)
6、案例:
php代码:
$row:一维数组 生成一个json格式的字符串
$data:二维数组 生成一个json数组格式的字符串
<?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数组对象
//alert(json[0].name+json[0].age);
}
};
xhr.send(null);
</script>
理解:
var json=eval('('+value+')'); 主要是针对关联数组
返回:"{name:'zhangsan',age:18}"
访问方式:json.username+json.password
var json=eval(value); 主要是针对索引数组
返回:"[{name:'zhangsan',age:18},{name:'lisi',age:20}]"
访问方式:json[0].name+json[0].age
注意:索引数组的解析也可以采用 var json=eval(value);
查询数据表中所有数据并生成json字符串返回
php代码:
<?php
//查询goods表中所有数据并返回
$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); //发送sql语句
$num=mysql_num_rows($result); //总行数
$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)
虽然最后实现的差强人意,不过也算是完成了功能,接下来就把我发现的一些问题和总结记录一下。
<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表单会造成页面刷新,因此,现在一般都采用按钮与 form 表单分离的方式,使用 AJAX来异步上传数据。 如下所示:
<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("服务器异常"); } }); }
代码已经保留了关键的代码部分,剔除了一些无关紧要的操作。
@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 循环的 getFiles(...) 如果取不到值的话,就会返回一个空的 List 不会直接抛出异常。
以上就是所有关键的代码部分,下面来说一说调试过程中我使用过的几种方法,以及觉得很坑的地方。
回看js 部分的代码,相信你已经注意到了:
var templates=$("#templatesFile")[0].files;
而FileList 并不是一个数组。如果希望将它转化成一个数组,可以使用 Array.from(FileList)
不过不论是 FileList还是数组,都不是重点,重点是$("#templatesFile")[0] 一定要加上后面的这个 [0] 。而如果使用document.getElementById("...")就不必加 [0]。 这是因为 files 属性是原生js属性,而不是jQuery属性,因此需要通过这个 [0] 将jQuery对象转化为 js对象,才能通过 .files 获得这个FileList !
说实话,前面的 js 与 java部分的代码实在是迫不得已,不过依然没有找到恰当合适的方法。
这个问题困扰了我整整一天的时间,从星期四的下午开始研究一直到第二天星期五的上午才勉强以上面的代码跑通功能。
之前做过上传单个文件的功能。那天我乐观的以为,只要前端能够获取到 files 数组,然后后端的接口使用 MultipartFile[] 来接收就可以大功告成了!像这样:
@RequestMapping(value="/uploadTemplates", method=RequestMethod.POST) @ResponseBody public String uploadTemplates(MultipartFile[] templates) { // ...some codes }
但是前端的代码我试过N种方法依然无法成功接收到这个文件数组!不论是这样:
还是这样:
亦或是将数组转化成String,然后后台用String接收:
都 完!全!没!用!
明明以前传其他类型的参数是OK的啊!这到底是为什么?
于是看到了 FormData 的解决方案。但是事情依然并!不!简!单!
一开始我的思路是封装一个FormData对象,然后把文件数组整体放入到一个value中,并且指定一个key ,这样后台通过 getFiles() 方法就可以获得整个文件列表了。
然鹅,并无卵用!
在网上找了下原因,看到了一些别人的代码,全都是每一个key放一个文件!原因是:
简单的说, String、Blob、File可以被FormData传输(注意这里是单个File类型的文件),如果是其他类型,则会被转化成字符串,然而,对于FileList又会是怎样的情况呢?我找到了下面这句话:
Using the FormData API is the simplest and fastest, but has the
disadvantage that data collected can not be stringified.
翻译过来就是,使用FormData最简单,也最高效,但是有一个缺点是,数据集合(比如List或者数组)无法被序列化为字符串。
简直就像是在耍人一样!我真的崩溃了!
也就是说,我必须将文件列表(或者数组)中的每一个文件取出来,分别给每一个文件指定一个Key才能成功的通过formdata传输到后台并接收。
所以才有了这样的代码:
// 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... }
到目前为止,还没有找到更加简洁和高效的代码,有哪位全栈的哥们可以告诉我吗?
欢迎评论区留言哦!非常感谢!
---欢迎关注【Java圣斗士】,我是你们的小可爱(?ω?) Morty---
---专注IT职场经验、IT技术分享的灵魂写手---
---每天带你领略IT的魅力---
---期待与您陪伴!---
前一直是用form表单,通过设置enctype="multipart/form-data"然后submit来上传文件的,但是在通过ajax方式跟后端进行数据交互时,这个方法就有点麻烦来,所以找到了ajax来上传文件的方法了。
下面是一个演示:
html文件
其中FormData是XMLHttpRequest Level 2的一个对象,有些浏览器可能不支持(感觉都支持的差不多了)。processData设置为false,网上说是data值是一个对象了,不需要对数据再做处理了,contentType设置为false,是不要设置Content-Type请求头了。请求类型还是post方式提交。
php代码
服务端php代码没做多少事情,就是把$_POST和$_FILES打印出来,同时通过move_uploaded_file方法把文件上传到当前目录。
上传成功的返回值
上传成功的返回值,利用console.log()函数打印出来了,可以看到,服务端中只用$_FILES有值,$_POST为空。
文件成功上传成功
上图显示文件上传到当前目录。
*请认真填写需求信息,我们会在24小时内与您取得联系。