SON對象有兩個方法:stringify()、parse()。
語法格式:stringify(參數1,[[參數2],[參數3]])
參數1:要被序列化的JavaScript對象
參數2:數據過濾器或轉換函數
如果是函數,傳入的函數接收兩個參數,屬性名和屬性值
JSON.stringify(str,function(key,value){return.......})
如果是數組,那么結果中將只包含數組中列出的屬性
JSON.stringify(str,["name","age"])
參數3:控制結果中的縮進和空白符
如果是一個數值,則表示每個級別縮進的空格數(<=10個)
JSON.stringify(str,["name","age"],4)
如果是一個字符串,則這個字符串將被用作縮進字符(不再使用空格)(<=10個)
JSON.stringify(str,["name","age"],"-")
如果還是不能滿足對某些對象進行自定義序列化的需求,可以給對象定義toJSON方法,返回其自身的JSON數據格式
var obj = {"name":"jack",toJSON:function(){....}}
備注:
1.1、序列化后的字符串不包含任何空格字符或縮進
1.2、所有函數及原型成員都會被忽略
1.3、值為undefined的任何屬性都會被跳過
語法格式:parse(參數1,[參數2])
參數1:要被解析的JSON字符串
參數2:是一個函數,傳入的函數接收兩個參數,屬性名和屬性值
JSON.parse(str,function(key,value){return.......})
HP獲取數據庫中數據生成json, 中文亂碼問題的解決方案
1.在代碼前段寫上
header("Content-Type: text/html;charset=utf8");
2.在connection建立以后寫上
mysqli_query($connection, "SET NAMES utf8");
————至此就可以在PHP頁面中顯示中文了————-
最后, 如果需要用到json_encode, 那么需要注意最后一點
$json_string = json_encode($result_row, JSON_UNESCAPED_UNICODE); //php5.4以上
即在普通的json_encode中多加入一個參數, 至此就全部完成啦~
讓json更懂中文(JSON_UNESCAPED_UNICODE)
<?php
echo json_encode("中文", JSON_UNESCAPED_UNICODE); //需要5.4以上版本才能支持 unescaped_unicode: unicode轉義
$data = array(
0=>array('status'=>'1', 'method'=>'登陸', 'message'=>'成功',"url"=>"http://q.qlogo.cn/qqapp/1105737075/788B369AB26335DDDFB5E45199B95FDD/40"),
1=>array('status'=>'2', 'method'=>'注銷', 'message'=>'成功',"url"=>"http://q.qlogo.cn/qqapp/1105737075/788B369AB26335DDDFB5E45199B95FDD/41"),
);
echo json_encode($data, JSON_UNESCAPED_UNICODE);
輸出結果:
[{"status":"1","method":"登陸","message":"成功","url":"http:\/\/q.qlogo.cn\/qqapp\/1105737075\/788B369AB26335DDDFB5E45199B95FDD\/40"},{"status":"2","method":"注銷","message":"成功","url":"http:\/\/q.qlogo.cn\/qqapp\/1105737075\/788B369AB26335DDDFB5E45199B95FDD\/41"}]
注意: 這個參數只解決中文轉碼問題, url地址自動加上轉義字符, 并未解決。
PHP5.4以上才支持JSON_UNESCAPED_UNICODE這個參數, 此參數是讓中文字符在json_encode的時候不用轉義, 減少數據傳輸量。但在PHP5.3中, 就得自己寫個函數來實現, 以下就是解決方法:
/**
* 對變量進行 JSON 編碼
* @param mixed value 待編碼的 value ,除了resource 類型之外,可以為任何數據類型,該函數只能接受 UTF-8 編碼的數據
* @return string 返回 value 值的 JSON 形式
*/
function json_encode_ex($value)
{
if (version_compare(PHP_VERSION,'5.4.0','<')){
$str = json_encode($value);
$str = preg_replace_callback("#\\\u([0-9a-f]{4})#i",
function($matchs){
return iconv('UCS-2BE', 'UTF-8', pack('H4', $matchs[1]));
},
$str
);
return $str;
}else{
return json_encode($value, JSON_UNESCAPED_UNICODE);
}
}
//使用方法
$data = array(
0=>array('status'=>'1', 'method'=>'登陸', 'message'=>'成功',"url"=>"http://q.qlogo.cn/qqapp/1105737075/788B369AB26335DDDFB5E45199B95FDD/40"),
1=>array('status'=>'2', 'method'=>'注銷', 'message'=>'成功',"url"=>"http://q.qlogo.cn/qqapp/1105737075/788B369AB26335DDDFB5E45199B95FDD/41"),
);
echo json_encode_ex($data); //這個函數只解決中文轉碼問題, url地址自動加上轉義字符, 并未解決
?>
輸出結果:
設我們有一個復雜的對象,我們希望將其轉換為字符串,以通過網絡發送,或者只是為了在日志中輸出它。
當然,這樣的字符串應該包含所有重要的屬性。
我們可以像這樣實現轉換:
let user = {
name: "John",
age: 30,
toString() {
return `{name: "${this.name}", age: ${this.age}}`;
}
};
alert(user); // {name: "John", age: 30}
……但在開發過程中,會新增一些屬性,舊的屬性會被重命名和刪除。每次更新這種 toString 都會非常痛苦。我們可以嘗試遍歷其中的屬性,但是如果對象很復雜,并且在屬性中嵌套了對象呢?我們也需要對它們進行轉換。
幸運的是,不需要編寫代碼來處理所有這些問題。這項任務已經解決了。
JSON(JavaScript Object Notation)是表示值和對象的通用格式。在 RFC 4627 標準中有對其的描述。最初它是為 JavaScript 而創建的,但許多其他編程語言也有用于處理它的庫。因此,當客戶端使用 JavaScript 而服務器端是使用 Ruby/PHP/Java 等語言編寫的時,使用 JSON 可以很容易地進行數據交換。
JavaScript 提供了如下方法:
例如,在這里我們 JSON.stringify 一個 student 對象:
let student = {
name: 'John',
age: 30,
isAdmin: false,
courses: ['html', 'css', 'js'],
wife: null
};
let json = JSON.stringify(student);
alert(typeof json); // we've got a string!
alert(json);
/* JSON 編碼的對象:
{
"name": "John",
"age": 30,
"isAdmin": false,
"courses": ["html", "css", "js"],
"wife": null
}
*/
方法 JSON.stringify(student) 接收對象并將其轉換為字符串。
得到的 json 字符串是一個被稱為 JSON 編碼(JSON-encoded) 或 序列化(serialized) 或 字符串化(stringified) 或 編組化(marshalled) 的對象。我們現在已經準備好通過有線發送它或將其放入普通數據存儲。
請注意,JSON 編碼的對象與對象字面量有幾個重要的區別:
JSON.stringify 也可以應用于原始(primitive)數據類型。
JSON 支持以下數據類型:
例如:
// 數字在 JSON 還是數字
alert( JSON.stringify(1) ) // 1
// 字符串在 JSON 中還是字符串,只是被雙引號擴起來
alert( JSON.stringify('test') ) // "test"
alert( JSON.stringify(true) ); // true
alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
JSON 是語言無關的純數據規范,因此一些特定于 JavaScript 的對象屬性會被 JSON.stringify 跳過。
即:
let user = {
sayHi() { // 被忽略
alert("Hello");
},
[Symbol("id")]: 123, // 被忽略
something: undefined // 被忽略
};
alert( JSON.stringify(user) ); // {}(空對象)
通常這很好。如果這不是我們想要的方式,那么我們很快就會看到如何自定義轉換方式。
最棒的是支持嵌套對象轉換,并且可以自動對其進行轉換。
例如:
let meetup = {
title: "Conference",
room: {
number: 23,
participants: ["john", "ann"]
}
};
alert( JSON.stringify(meetup) );
/* 整個解構都被字符串化了
{
"title":"Conference",
"room":{"number":23,"participants":["john","ann"]},
}
*/
重要的限制:不得有循環引用。
例如:
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: ["john", "ann"]
};
meetup.place = room; // meetup 引用了 room
room.occupiedBy = meetup; // room 引用了 meetup
JSON.stringify(meetup); // Error: Converting circular structure to JSON
在這里,轉換失敗了,因為循環引用:room.occupiedBy 引用了 meetup,meetup.place 引用了 room:
JSON.stringify 的完整語法是:
let json = JSON.stringify(value[, replacer, space])
value要編碼的值。replacer要編碼的屬性數組或映射函數 function(key, value)。space用于格式化的空格數量
大部分情況,JSON.stringify 僅與第一個參數一起使用。但是,如果我們需要微調替換過程,比如過濾掉循環引用,我們可以使用 JSON.stringify 的第二個參數。
如果我們傳遞一個屬性數組給它,那么只有這些屬性會被編碼。
例如:
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: [{name: "John"}, {name: "Alice"}],
place: room // meetup 引用了 room
};
room.occupiedBy = meetup; // room 引用了 meetup
alert( JSON.stringify(meetup, ['title', 'participants']) );
// {"title":"Conference","participants":[{},{}]}
這里我們可能過于嚴格了。屬性列表應用于了整個對象結構。所以 participants 是空的,因為 name 不在列表中。
讓我們包含除了會導致循環引用的 room.occupiedBy 之外的所有屬性:
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: [{name: "John"}, {name: "Alice"}],
place: room // meetup 引用了 room
};
room.occupiedBy = meetup; // room 引用了 meetup
alert( JSON.stringify(meetup, ['title', 'participants', 'place', 'name', 'number']) );
/*
{
"title":"Conference",
"participants":[{"name":"John"},{"name":"Alice"}],
"place":{"number":23}
}
*/
現在,除 occupiedBy 以外的所有內容都被序列化了。但是屬性的列表太長了。
幸運的是,我們可以使用一個函數代替數組作為 replacer。
該函數會為每個 (key,value) 對調用并返回“已替換”的值,該值將替換原有的值。如果值被跳過了,則為 undefined。
在我們的例子中,我們可以為 occupiedBy 以外的所有內容按原樣返回 value。為了 occupiedBy,下面的代碼返回 undefined:
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: [{name: "John"}, {name: "Alice"}],
place: room // meetup 引用了 room
};
room.occupiedBy = meetup; // room 引用了 meetup
alert( JSON.stringify(meetup, function replacer(key, value) {
alert(`${key}: ${value}`);
return (key == 'occupiedBy') ? undefined : value;
}));
/* key:value pairs that come to replacer:
: [object Object]
title: Conference
participants: [object Object],[object Object]
0: [object Object]
name: John
1: [object Object]
name: Alice
place: [object Object]
number: 23
*/
請注意 replacer 函數會獲取每個鍵/值對,包括嵌套對象和數組項。它被遞歸地應用。replacer 中的 this 的值是包含當前屬性的對象。
第一個調用很特別。它是使用特殊的“包裝對象”制作的:{"": meetup}。換句話說,第一個 (key, value) 對的鍵是空的,并且該值是整個目標對象。這就是上面的示例中第一行是 ":[object Object]" 的原因。
這個理念是為了給 replacer 提供盡可能多的功能:如果有必要,它有機會分析并替換/跳過整個對象。
JSON.stringify(value, replacer, spaces) 的第三個參數是用于優化格式的空格數量。
以前,所有字符串化的對象都沒有縮進和額外的空格。如果我們想通過網絡發送一個對象,那就沒什么問題。space 參數專門用于調整出更美觀的輸出。
這里的 space = 2 告訴 JavaScript 在多行中顯示嵌套的對象,對象內部縮緊 2 個空格:
let user = {
name: "John",
age: 25,
roles: {
isAdmin: false,
isEditor: true
}
};
alert(JSON.stringify(user, null, 2));
/* 兩個空格的縮進:
{
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
/* 對于 JSON.stringify(user, null, 4) 的結果會有更多縮進:
{
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
spaces 參數僅用于日志記錄和美化輸出。
像 toString 進行字符串轉換,對象也可以提供 toJSON 方法來進行 JSON 轉換。如果可用,JSON.stringify 會自動調用它。
例如:
let room = {
number: 23
};
let meetup = {
title: "Conference",
date: new Date(Date.UTC(2017, 0, 1)),
room
};
alert( JSON.stringify(meetup) );
/*
{
"title":"Conference",
"date":"2017-01-01T00:00:00.000Z", // (1)
"room": {"number":23} // (2)
}
*/
在這兒我們可以看到 date (1) 變成了一個字符串。這是因為所有日期都有一個內置的 toJSON 方法來返回這種類型的字符串。
現在讓我們為對象 room 添加一個自定義的 toJSON:
let room = {
number: 23,
toJSON() {
return this.number;
}
};
let meetup = {
title: "Conference",
room
};
alert( JSON.stringify(room) ); // 23
alert( JSON.stringify(meetup) );
/*
{
"title":"Conference",
"room": 23
}
*/
正如我們所看到的,toJSON 既可以用于直接調用 JSON.stringify(room) 也可以用于當 room 嵌套在另一個編碼對象中時。
要解碼 JSON 字符串,我們需要另一個方法 JSON.parse。
語法:
let value = JSON.parse(str, [reviver]);
str要解析的 JSON 字符串。reviver可選的函數 function(key,value),該函數將為每個 (key, value) 對調用,并可以對值進行轉換。
例如:
// 字符串化數組
let numbers = "[0, 1, 2, 3]";
numbers = JSON.parse(numbers);
alert( numbers[1] ); // 1
對于嵌套對象:
let userData = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }';
let user = JSON.parse(userData);
alert( user.friends[1] ); // 1
JSON 可能會非常復雜,對象和數組可以包含其他對象和數組。但是它們必須遵循相同的 JSON 格式。
以下是手寫 JSON 時的典型錯誤(有時我們必須出于調試目的編寫它):
let json = `{
name: "John", // 錯誤:屬性名沒有雙引號
"surname": 'Smith', // 錯誤:值使用的是單引號(必須使用雙引號)
'isAdmin': false // 錯誤:鍵使用的是單引號(必須使用雙引號)
"birthday": new Date(2000, 2, 3), // 錯誤:不允許使用 "new",只能是裸值
"friends": [0,1,2,3] // 這個沒問題
}`;
此外,JSON 不支持注釋。向 JSON 添加注釋無效。
還有另一種名為 JSON5 的格式,它允許未加引號的鍵,也允許注釋等。但這是一個獨立的庫,不在語言的規范中。
常規的 JSON 格式嚴格,并不是因為它的開發者很懶,而是為了實現簡單,可靠且快速地實現解析算法。
想象一下,我們從服務器上獲得了一個字符串化的 meetup 對象。
它看起來像這樣:
// title: (meetup title), date: (meetup date)
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
……現在我們需要對它進行 反序列(deserialize),把它轉換回 JavaScript 對象。
讓我們通過調用 JSON.parse 來完成:
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let meetup = JSON.parse(str);
alert( meetup.date.getDate() ); // Error!
啊!報錯了!
meetup.date 的值是一個字符串,而不是 Date 對象。JSON.parse 怎么知道應該將字符串轉換為 Date 呢?
讓我們將 reviver 函數傳遞給 JSON.parse 作為第二個參數,該函數按照“原樣”返回所有值,但是 date 會變成 Date:
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let meetup = JSON.parse(str, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( meetup.date.getDate() ); // 現在正常運行了!
順便說一下,這也適用于嵌套對象:
let schedule = `{
"meetups": [
{"title":"Conference","date":"2017-11-30T12:00:00.000Z"},
{"title":"Birthday","date":"2017-04-18T12:00:00.000Z"}
]
}`;
schedule = JSON.parse(schedule, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( schedule.meetups[1].date.getDate() ); // 正常運行了!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。