日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php json对象取数据类型,PHP如何科学地json_encode类对象数据

發(fā)布時間:2025/4/16 php 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php json对象取数据类型,PHP如何科学地json_encode类对象数据 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

其實這篇文章更應該針對python, 因為python默認情況下json序列化一個類對象時,是要報錯的。

但是我覺得php的碼農更多吧,而且主要是想傳達一種思想,思想無國界哈。

那就拿PHP舉粟,我們先來看看

1. json_encode對類的處理

先來看段測試代碼:

class A {

public $a;

public $b;

private $c;

static public $d;

static protected $e;

public function __construct(){

$this->a = 1;

$this->b = 2;

$this->c = 3;

self::$d = 4;

self::$e = 5;

}

}

$obj = new A;

echo json_encode($obj);

輸出結果為:

>> {"a":1,"b":2}

get_object_vars() 裝飾下輸出代碼:

echo json_encode( get_object_vars($obj) );

輸出結果還是:

>> {"a":1,"b":2}

綜上我們差不多可以作個結論:

json_encode()序列化一個對象時,會先提取(get_object_vars)對象的公有(public)屬性合并為一個數(shù)組,再進行序列化。private、protected、static屬性以及類方法都將被丟棄。

1.1 不改變屬性聲明如何自定義JSON序列化的字段?

好,實操中真正碰到的問題來了。

class A {

public $a;

public $b;

public function __construct($a, $b){

$this->a = $a;

$this->b = $b;

}

public function sum(){

return $this->a + $this->b;

}

}

$obj = new A(1,2);

我想json_encode得到一個sum字段,如:

{"a":1, "b":2, "sum":3}

怎么實現(xiàn)呢?

童鞋們還得記PHP的類有個魔法方法 __toString(), 該方法是當嘗試將對象轉化為字符串時,就會調用該函數(shù),從而得到期望的字符串。

class B{

public function __toString(){

return "我只是個大B";

}

}

echo(new B); // such as print(), strval(), ...

>> 我只是個大B

如果你是個Python coder, 這就不足為奇了,因為python的魔法方法真的不要花樣太多。

好吧,那么有沒有一個神奇的方法如 __json() 讓我們來實現(xiàn)自定義JSON序列化呢?

暫時沒有,不過PHP作者們早接到了這種需求,并做出了解決方案,請看:

1.2 接口JsonSerializable::jsonSerialize(),了解一下!

系統(tǒng)支持:(PHP 5 >= 5.4.0, PHP 7)

怎么用呢?看代碼:

// 1. 類先要實現(xiàn)JsonSerializable接口

class A implements JsonSerializable {

public $a;

public $b;

public function __construct($a, $b){

$this->a = $a;

$this->b = $b;

}

public function sum(){

return $this->a + $this->b;

}

// 2. 實現(xiàn)jsonSerialize() 方法

public function jsonSerialize(){

// 定義我們需要的字段

return array(

"a"=>$this->a,

"b"=>$this->b,

"sum"=>$this->sum()

);

}

}

$obj = new A(1,2);

echo json_encode($obj);

這下滿意了吧,看:

>> {"a":1,"b":2,"sum":3}

當類實現(xiàn)了jsonSerialize()時,json_encode(object)將使用jsonSerialize()取代get_object_vars()得到需要序列化的字段信息。

1.3 DateTime等系統(tǒng)對象如何處理

由于這些類是系統(tǒng)定義的,顯示是無法添加上邊說的接口,再定義一個子類做兼容也是個工作量不小的問題。

echo json_encode(date_create());

>> {"date":"2019-12-17 07:49:24.086271", "timezone_type":3, "timezone":"UTC"}

然而,因業(yè)務需求,所有接口里返回的時間對象,我只想要統(tǒng)一為:

YYYY-MM-DD HH:MM:SS 這種格式字符串

因此,建議大家在框架應用時

2. 自定義自己的json_encode方法

json_encode()顯然是無法重寫的了,那我就自己定義一個方法

2.1 my_json_encode()

然后整個項目查找json_encode替換為my_json_encode即可快速解決。

定義一個完全兼容json_encode()參數(shù)的方法

function my_json_encode($value, $options=0, $depth=512){

$value = my_json_handle($value);

return json_encode($value, $options, $depth);

}

代碼里定義一個個性化的序列化處理方法:

2.2 my_json_handle($value)

在這里,你可以定義任何數(shù)據(jù)類型如何JSON序列化。

function my_json_handle($mixed, $depth=512, $recursion=1){

// recursion limited.

if($recursion >= $depth){

return print_r($mixed, true);

}

// 這是一個類對象數(shù)據(jù)

if(is_object($mixed)){

// 假設遇到DateTime數(shù)據(jù), 輸出為我們想要的

if($mixed instanceof DateTime || $mixed instanceof DateTimeImmutable){

return date_format($mixed, 'Y-m-d H:i:s');

}

// 你可以在這里自定義更多系統(tǒng)預設類的處理...

// 優(yōu)先兼容實現(xiàn)了jsonSerialize()方法的類.

if($mixed instanceof JsonSerializable){

$mixed = $mixed->jsonSerialize();

}

elseif(method_exists($mixed, "__json")){

// 添加 __json() 魔法方法支持.

// 個人感覺 __json()比jsonSerialize()更科學且好記

// 類不需要再 implements JsonSerializable

$mixed = $mixed->__json();

}

// 默認get_object_vars()提取屬性字段

if(is_object($mixed)){

$mixed = get_object_vars($mixed);

}

// 上邊的if判斷里沒有像DateTime那樣直接return $mixed

// 是因為可能得到是個可迭代的數(shù)據(jù), 我們需要再進行迭代處理

}

// 可迭代的嵌套數(shù)據(jù)

if(is_array($mixed)){

foreach($mixed as $k=>$v){

// 當前迭代層級+1

$mixed[$k] = my_json_handle($v, $depth, $recursion+1);

}

}

return $mixed;

}

2.3 測試下我們的成果

// 不需要再 implements JsonSerializable

class A {

public $a;

public $b;

public $datetime;

public function __construct($a, $b){

$this->a = $a;

$this->b = $b;

$this->datetime = date_create("now", new DateTimeZone('+0800'));

}

public function sum(){

return $this->a + $this->b;

}

// 只需實現(xiàn) __json() 方法

public function __json(){

// 定義我們需要的字段

return array(

"datetime"=>$this->datetime,

"timestamp"=>$this->datetime->getTimestamp(),

"sum"=>$this->sum()

);

}

}

echo my_json_encode(new A(1,2));

>> {"datetime":"2019-12-17 16:34:15", "timestamp":1576571655, "sum":3}

當你在項目中=使用ORM框架,并定義了大量的Model,在json序列化這些Model時,你會發(fā)現(xiàn)這篇文章還是有很實用的。

能規(guī)范你的接口輸出字段,ajax接口不會經(jīng)常多字段或少字段,同一個字段一會是字符串一會又是整型的各種尷尬。

后記

PHP中的標量(Scalar Data), 目前只發(fā)現(xiàn)float浮點數(shù)據(jù)在json_encode時可能出現(xiàn)溢出,PHP7可通過配置

serialize_precision = -1

解決。

另外瀏覽器端可能不支持長整型,有些訂單ID位數(shù)比較長的時候(大于32bit整數(shù)),瀏覽器端JSON.parse()的時候就容易被截短數(shù)據(jù),后臺處理時可以把它轉化為字符串。

《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的php json对象取数据类型,PHP如何科学地json_encode类对象数据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。