JsonSerializable::jsonSerialize

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

JsonSerializable::jsonSerialize指定应序列化为 JSON 的数据

说明

public JsonSerializable::jsonSerialize(): 混合

将对象序列化为 json_encode() 可以原生序列化的值。

参数

此函数没有参数。

返回值

返回可以被 json_encode() 序列化的数据,它是一个除了 资源 以外的任何类型的值。

示例

示例 #1 JsonSerializable::jsonSerialize() 示例,返回一个 数组

<?php
class ArrayValue implements JsonSerializable {
private
$array;
public function
__construct(array $array) {
$this->array = $array;
}

public function
jsonSerialize(): mixed {
return
$this->array;
}
}

$array = [1, 2, 3];
echo
json_encode(new ArrayValue($array), JSON_PRETTY_PRINT);
?>

上面的示例将输出

[
    1,
    2,
    3
]

示例 #2 JsonSerializable::jsonSerialize() 示例,返回一个关联 数组

<?php
class ArrayValue implements JsonSerializable {
private
$array;
public function
__construct(array $array) {
$this->array = $array;
}

public function
jsonSerialize() {
return
$this->array;
}
}

$array = ['foo' => 'bar', 'quux' => 'baz'];
echo
json_encode(new ArrayValue($array), JSON_PRETTY_PRINT);
?>

上面的示例将输出

{
    "foo": "bar",
    "quux": "baz"
}

示例 #3 JsonSerializable::jsonSerialize() 示例,返回一个 整数

<?php
class IntegerValue implements JsonSerializable {
private
$number;
public function
__construct($number) {
$this->number = (int) $number;
}

public function
jsonSerialize() {
return
$this->number;
}
}

echo
json_encode(new IntegerValue(1), JSON_PRETTY_PRINT);
?>

上面的示例将输出

1

示例 #4 JsonSerializable::jsonSerialize() 示例,返回一个 字符串

<?php
class StringValue implements JsonSerializable {
private
$string;
public function
__construct($string) {
$this->string = (string) $string;
}

public function
jsonSerialize() {
return
$this->string;
}
}

echo
json_encode(new StringValue('Hello!'), JSON_PRETTY_PRINT);
?>

上面的示例将输出

"Hello!"

添加注释

用户贡献注释 9 个注释

78
benkuhl at gmail dot com
11 年前
使用这种功能的一个好例子是在处理对象时。

json_encode() 会将 DateTime 转换为

{
"date":"2013-01-31 11:14:05",
"timezone_type":3,
"timezone":"America\/Los_Angeles"
}

这在使用 PHP 时很棒,但是如果日期被 Java 读取,Java 日期解析器就不知道该怎么做。但它确实知道如何处理 ISO8601 格式...

<?php

date_default_timezone_set
('America/Los_Angeles');

class
Fruit implements JsonSerializable {
public
$type = 'Apple',
$lastEaten = null;

public function
__construct() {
$this->lastEaten = new DateTime();
}

public function
jsonSerialize() {
return [
'type' => $this->type,
'lastEaten' => $this->lastEaten->format(DateTime::ISO8601)
];
}
}
echo
json_encode(new Fruit()); //which outputs: {"type":"Apple","lastEaten":"2013-01-31T11:17:07-0500"}

?>
16
tomasz dot darmetko at gmail dot com
7 年前
嵌套的 json 可序列化对象将被递归地序列化。无需自己调用 ->jsonSerialize()。它在集合中特别有用。

<?php

class NestedSerializable implements \JsonSerializable
{

private
$serializable;

public function
__construct($serializable)
{
$this->serializable = $serializable;
}

public function
jsonSerialize()
{
return [
'serialized' => $this->serializable
];
}

}

class
SerializableCollection implements \JsonSerializable {

private
$elements;

public function
__construct(array $elements)
{
$this->elements = $elements;
}

public function
jsonSerialize()
{
return
$this->elements;
}

}

// 输出: [{"serialized":null},{"serialized":null},{"serialized":{"serialized":null}}]
echo json_encode(
new
SerializableCollection([
new
NestedSerializable(null),
new
NestedSerializable(null),
new
NestedSerializable(new NestedSerializable(null))
])
);

?>
5
info at digistratum dot com
7 年前
这是一个简单的测试/证明,可以方便地看到一些对比结果。我感兴趣的是 Null,因为它没有被文档记录。

<?php
class jsontest implements JsonSerializable {
function
__construct($value) { $this->value = $value; }
function
jsonSerialize() { return $this->value; }
}

print
"Null -> " . json_encode(new jsontest(null)) . "\n";
print
"Array -> " . json_encode(new jsontest(Array(1,2,3))) . "\n";
print
"Assoc. -> " . json_encode(new jsontest(Array('a'=>1,'b'=>3,'c'=>4))) . "\n";
print
"Int -> " . json_encode(new jsontest(5)) . "\n";
print
"String -> " . json_encode(new jsontest('Hello, World!')) . "\n";
print
"Object -> " . json_encode(new jsontest((object) Array('a'=>1,'b'=>3,'c'=>4))) . "\n";
?>

输出结果是
Null -> null
Array -> [1,2,3]
Assoc. -> {"a":1,"b":3,"c":4}
Int -> 5
String -> "Hello, World!"
Object -> {"a":1,"b":3,"c":4}
1
david at vanlaatum dot id dot au
9 年前
simonsimcity at gmail dot com 说错了,你可以在里面抛出异常,但它会用另一个异常包装,所以他的例子输出

PHP 致命错误: 未捕获的异常“RuntimeException”且消息为“It failed!” 在 -:8
堆栈跟踪
#0 [内部函数]: Foo->jsonSerialize()
#1 -(16): json_encode(Object(Foo))
#2 {主程序}

下一个异常“Exception”且消息为“Failed calling Foo::jsonSerialize()” 在 -:16
堆栈跟踪
#0 -(0): json_encode()
#1 {主程序}
在 - 的第 16 行抛出

PHP 5.4.39
-8
Anonymous
9 年前
在 PHP 5.3 中将私有属性序列化为 JSON

<?php

abstract class Model {

public function
jsonSerialize() {
$getter_names = get_class_methods(get_class($this));
$gettable_attributes = array();
foreach (
$getter_names as $key => $value) {
if(
substr($value, 0, 4) === 'get_') {
$gettable_attributes[substr($value, 4, strlen($value))] = $this->$value();
}
}
return
$gettable_attributes;
}

}

class
Content extends Model {

private
$title;
private
$text;

public function
get_title() {
return
$this->title;
}

public function
set_title($title) {
$this->title = $title;
}

public function
get_text() {
return
$this->text;
}

public function
set_text($text) {
$this->text = $text;
}


}

$content = new Content();
$content->set_title('lol');
$content->set_text('haha');

echo
json_encode($content->jsonSerialize());
?>
-14
simonsimcity at gmail dot com
10 年前
你不能在这里抛出异常。如果你这样做,你会得到一个带有消息“Failed calling FooClass::jsonSerialize()”的异常,并且堆栈跟踪将从你调用 json_encode() 方法的地方开始。

这是一个代码示例

class Foo implements JsonSerializable {
private $triggerError = true;

public function jsonSerialize()
{
if ($this->triggerError) {
throw new RuntimeException("It failed!");
}

return (array)$this;
}
}

// 将抛出一个异常,例如 new Exception("Failed calling Foo::jsonSerialize()")
json_encode(new Foo());
-5
rmdundon at gmail dot com
5 年前
对于那些也懒惰的人来说。你不能只是包含 $this 并期望它能工作。

例如,这将不起作用

<?php
class SomeClass implements JsonSerializable {

protected
$partner;

function
setPartner(object $partner) {
$this->partner;
}

public function
jsonSerialize() {
return
$this;
}
}

$foo = new SomeClass();
$too = new stdClass();
$too->test = 1;
$foo->setPartner = $too;

echo
json_encode($foo); // 显示一个空对象 "{}"

?>

你必须手动定义这些东西,所以这将起作用。

<?php
class SomeClass implements JsonSerializable {

protected
$partner;

function
setPartner(object $partner) {
$this->partner;
}

public function
jsonSerialize() {
$data['partner'] = $this->partner;
return
$data;
}
}

$foo = new SomeClass();
$too = new stdClass();
$too->test = 1;
$foo->setPartner = $too;

echo
json_encode($foo); // 显示 {"partner":{"test":1}}
-16
dimstefan83 at gmail dot com
10 年前
简单函数让生活更轻松。
我想要一种方法,让属性值成为方法的返回值,以便将其初始化。示例

class portItem implements JsonSerializable{
private $idPort;
private $location;
private $portLanguages;

public function getLocation() {
if(!isset($this->location)){
return new locationItem();
}
return $this->location;
}

public function setLocation($location) {
$this->location = $location;
}

public function setidPort($idPort){
$this->idPort=$idPort;
}

public function getidPort(){
如果 (!isset($this->idPort)) {
return 0;
}
return intval($this->idPort);
}
public function setPortLanguages($portLanguages) {
$this->portLanguages = $portLanguages;
}

public function getPortLanguages() {
if (!isset($this->portLanguages)) {
return new genericItems();
}
return $this->portLanguages;
}

public function getCategoryLanguages() {
if (!isset($this->portLanguages)) {
return new genericItems();
}
return $this->portLanguages;
}

public function getPortLanguageAtIndex($index = false) {
if (!$index) {
$index = 0;
}
return $this->portLanguages[$index];
}

public function setPortLanguageAtIndex($index, $language) {
$this->portLanguages[$index] = $language;
}

public function jsonSerialize() {
$dataConverter = new dataConverter();
return $dataConverter->convertToJson($this);
}

}

有两种方法可以自动转换为 json。
1. 通过读取属性
public function convertToJson($object) {
/* 使用对象属性的方法 */
$class = get_class($this);
$json = array();
$properties = get_class_vars($class);
$keys = array_keys($properties);
$plength = count($keys);
for ($i = 0; $i < $plength; $i++) {
$method = "get" . $keys[$i];
if (method_exists($this, $method)) {
$json[$keys[$i]] = $this->$method();
}
}
return $json;
}

public function convertToJson($object) {
/* 使用对象方法的方法 */
$class = get_class($object);
$json = array();
$methods = get_class_methods($class);
$plength = count($methods);
$json = array();
for ($i = 0; $i < $plength; $i++) {
if (stripos($methods[$i], "get") !== FALSE) {
$property = mb_substr($methods[$i], 3, mb_strlen($methods[$i], 'UTF-8'), 'UTF-8');
$setter = "set" . mb_substr($methods[$i], 3, mb_strlen($methods[$i], 'UTF-8'), 'UTF-8');
if (method_exists($object, $setter)) {
$json[$property] = $object->$methods[$i]();
}

}
}

return $json;
}

使用这种方法,结果将是一个 json,其中属性的值根据每个方法初始化。

需要注意的事项
1. 如果你使用读取属性方法,代码不能在类外部工作,因为私有属性是不可见的,你必须直接将代码放在 public function jsonSerialize() {} 中才能工作。
2. 对于两种方法来说,方法似乎不区分大小写,否则你会遇到问题,我强烈建议你注意属性名称和方法名称之间的命名约定:idPort => setIdPort() => getIdPort()(我知道我的类没有这样做)。
3. 由于这两种方法都调用方法而不知道参数,你需要注意 getter 方法中的参数,看看我的例子
public function getPortLanguageAtIndex($index = false) {
if (!$index) {
$index = 0;
}
return $this->portLanguages[$index];
}
这就是为什么我将其设置为可选参数的原因。如果你不这样做,PHP 会抱怨方法 XXX 中缺少参数。
-10
c dot waltjen at posteo dot de
3 年前
Json Serializable 不会分析结果以序列化子属性。
我们必须手动调用它们
<?php

class A implements JsonSerializable
{
private
B $b;

public function
__construct(B $b) { $this->b = $b;}

public function
jsonSerialize(): array
{
return [
'b' => $this->b->jsonSerialize()];
}
}

class
B
{
private
string $foo = '';

public function
__construct(string $foo) { $this->foo = $foo; }

public function
jsonSerialize(): array
{
return [
'foo' => $this->foo];
}
}

$a = new A(new B('Hallo Welt'));

var_dump(json_encode($a));
?>

结果是
string(26) "{"b":{"foo":"Hallo Welt"}}"
To Top