Skip to content

Commit f9f8c1c

Browse files
committed
Optimized object encoding without rebulding properties HashTable
1 parent 87a5a0e commit f9f8c1c

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

ext/json/json_encoder.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,67 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
115115
myht = Z_ARRVAL_P(val);
116116
prop_ht = NULL;
117117
r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : php_json_determine_array_type(val);
118+
} else if (Z_OBJ_P(val)->properties == NULL
119+
&& Z_OBJ_HT_P(val)->get_properties_for == NULL
120+
&& Z_OBJ_HT_P(val)->get_properties == zend_std_get_properties) {
121+
/* Optimized version without rebulding properties HashTable */
122+
zend_object *obj = Z_OBJ_P(val);
123+
zend_class_entry *ce = obj->ce;
124+
zend_property_info *prop_info;
125+
zval *prop;
126+
int i;
127+
128+
if (GC_IS_RECURSIVE(obj)) {
129+
encoder->error_code = PHP_JSON_ERROR_RECURSION;
130+
smart_str_appendl(buf, "null", 4);
131+
return FAILURE;
132+
}
133+
134+
PHP_JSON_HASH_PROTECT_RECURSION(obj);
135+
smart_str_appendc(buf, '{');
136+
for (i = 0; i < ce->default_properties_count; i++) {
137+
prop_info = ce->properties_info_table[i];
138+
if (!prop_info) {
139+
continue;
140+
}
141+
if (ZSTR_VAL(prop_info->name)[0] == '\0' && ZSTR_LEN(prop_info->name) > 0) {
142+
/* Skip protected and private members. */
143+
continue;
144+
}
145+
prop = OBJ_PROP(obj, prop_info->offset);
146+
if (Z_TYPE_P(prop) == IS_UNDEF) {
147+
continue;
148+
}
149+
150+
if (need_comma) {
151+
smart_str_appendc(buf, ',');
152+
} else {
153+
need_comma = 1;
154+
}
155+
156+
php_json_pretty_print_char(buf, options, '\n');
157+
php_json_pretty_print_indent(buf, options, encoder);
158+
159+
if (php_json_escape_string(buf, ZSTR_VAL(prop_info->name), ZSTR_LEN(prop_info->name),
160+
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE &&
161+
(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) &&
162+
buf->s) {
163+
ZSTR_LEN(buf->s) -= 4;
164+
smart_str_appendl(buf, "\"\"", 2);
165+
}
166+
167+
smart_str_appendc(buf, ':');
168+
php_json_pretty_print_char(buf, options, ' ');
169+
170+
if (php_json_encode_zval(buf, prop, options, encoder) == FAILURE &&
171+
!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
172+
PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
173+
return FAILURE;
174+
}
175+
}
176+
smart_str_appendc(buf, '}');
177+
PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
178+
return SUCCESS;
118179
} else {
119180
prop_ht = myht = zend_get_properties_for(val, ZEND_PROP_PURPOSE_JSON);
120181
r = PHP_JSON_OUTPUT_OBJECT;

0 commit comments

Comments
 (0)