]> granicus.if.org Git - php/commitdiff
Fix json_encode regression with JSON_PRETTY_PRINT
authorTyson Andre <tysonandre775@hotmail.com>
Sat, 27 Mar 2021 19:19:08 +0000 (15:19 -0400)
committerTyson Andre <tysonandre775@hotmail.com>
Sat, 27 Mar 2021 22:47:54 +0000 (18:47 -0400)
This makes the json encoding behavior the same as it was prior to the memory
optimizations added in f9f8c1c79cac1b03279190e0c5513a51881615f9
(for objects with declared properties)

This is based on the code for the unoptimized case below the changes.

Buggy output prior to this commit:
```
{
"prop":"value"}
```

Correct output:

```
{
    "prop": "value"
}
```

Closes GH-6811

ext/json/json_encoder.c
ext/json/tests/json_encode_pretty_print2.phpt [new file with mode: 0644]

index c76ddaf0fdd8922077910ba37c5bca550f475b00..2888a7090ce7e707b97ba4548b4fde5c97c92091 100644 (file)
@@ -119,7 +119,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
        } else if (Z_OBJ_P(val)->properties == NULL
         && Z_OBJ_HT_P(val)->get_properties_for == NULL
         && Z_OBJ_HT_P(val)->get_properties == zend_std_get_properties) {
-               /* Optimized version without rebulding properties HashTable */
+               /* Optimized version without rebuilding properties HashTable */
                zend_object *obj = Z_OBJ_P(val);
                zend_class_entry *ce = obj->ce;
                zend_property_info *prop_info;
@@ -133,7 +133,11 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
                }
 
                PHP_JSON_HASH_PROTECT_RECURSION(obj);
+
                smart_str_appendc(buf, '{');
+
+               ++encoder->depth;
+
                for (i = 0; i < ce->default_properties_count; i++) {
                        prop_info = ce->properties_info_table[i];
                        if (!prop_info) {
@@ -174,6 +178,13 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
                                return FAILURE;
                        }
                }
+
+               --encoder->depth;
+
+               if (need_comma) {
+                       php_json_pretty_print_char(buf, options, '\n');
+                       php_json_pretty_print_indent(buf, options, encoder);
+               }
                smart_str_appendc(buf, '}');
                PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
                return SUCCESS;
diff --git a/ext/json/tests/json_encode_pretty_print2.phpt b/ext/json/tests/json_encode_pretty_print2.phpt
new file mode 100644 (file)
index 0000000..e872852
--- /dev/null
@@ -0,0 +1,55 @@
+--TEST--
+json_encode() with JSON_PRETTY_PRINT on declared properties
+--FILE--
+<?php
+class MyClass {
+    public $x;
+    public $y;
+    public function __construct($x = 123, $y = []) {
+        $this->x = $x;
+        $this->y = $y;
+    }
+}
+
+class HasNoProperties {}
+
+echo json_encode(new HasNoProperties()), "\n";
+echo json_encode(new HasNoProperties(), JSON_PRETTY_PRINT), "\n";
+
+echo json_encode(new MyClass()), "\n";
+echo json_encode(new MyClass(), JSON_PRETTY_PRINT), "\n";
+$obj = new MyClass();
+$obj->dynamic = new MyClass(null, []);
+echo json_encode($obj), "\n";
+echo json_encode($obj, JSON_PRETTY_PRINT), "\n";
+$obj = new MyClass();
+unset($obj->y);
+echo json_encode($obj), "\n";
+echo json_encode($obj, JSON_PRETTY_PRINT), "\n";
+unset($obj->x);
+echo json_encode($obj), "\n";
+echo json_encode($obj, JSON_PRETTY_PRINT), "\n";
+?>
+--EXPECT--
+{}
+{}
+{"x":123,"y":[]}
+{
+    "x": 123,
+    "y": []
+}
+{"x":123,"y":[],"dynamic":{"x":null,"y":[]}}
+{
+    "x": 123,
+    "y": [],
+    "dynamic": {
+        "x": null,
+        "y": []
+    }
+}
+{"x":123}
+{
+    "x": 123
+}
+{}
+{}
\ No newline at end of file