Merge pull request #99765 from dalexeev/core-fix-json-from-to-native

Core: Fix `JSON.{from,to}_native()` issues
This commit is contained in:
Thaddeus Crews
2024-12-10 14:15:53 -06:00
15 changed files with 1237 additions and 874 deletions

File diff suppressed because it is too large Load Diff

View File

@ -80,6 +80,9 @@ class JSON : public Resource {
static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str);
static Error _parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
static Variant _from_native(const Variant &p_variant, bool p_full_objects, int p_depth);
static Variant _to_native(const Variant &p_json, bool p_allow_objects, int p_depth);
protected:
static void _bind_methods();
@ -90,13 +93,18 @@ public:
static String stringify(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false);
static Variant parse_string(const String &p_json_string);
inline Variant get_data() const { return data; }
void set_data(const Variant &p_data);
inline int get_error_line() const { return err_line; }
inline String get_error_message() const { return err_str; }
_FORCE_INLINE_ static Variant from_native(const Variant &p_variant, bool p_full_objects = false) {
return _from_native(p_variant, p_full_objects, 0);
}
_FORCE_INLINE_ static Variant to_native(const Variant &p_json, bool p_allow_objects = false) {
return _to_native(p_json, p_allow_objects, 0);
}
static Variant from_native(const Variant &p_variant, bool p_allow_classes = false, bool p_allow_scripts = false);
static Variant to_native(const Variant &p_json, bool p_allow_classes = false, bool p_allow_scripts = false);
void set_data(const Variant &p_data);
_FORCE_INLINE_ Variant get_data() const { return data; }
_FORCE_INLINE_ int get_error_line() const { return err_line; }
_FORCE_INLINE_ String get_error_message() const { return err_str; }
};
class ResourceFormatLoaderJSON : public ResourceFormatLoader {

View File

@ -33,6 +33,7 @@
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/variant/container_type_validate.h"
#include <limits.h>
#include <stdio.h>
@ -84,12 +85,6 @@ enum ContainerTypeKind {
CONTAINER_TYPE_KIND_SCRIPT = 0b11,
};
struct ContainerType {
Variant::Type builtin_type = Variant::NIL;
StringName class_name;
Ref<Script> script;
};
#define GET_CONTAINER_TYPE_KIND(m_header, m_field) \
((ContainerTypeKind)(((m_header) & HEADER_DATA_FIELD_##m_field##_MASK) >> HEADER_DATA_FIELD_##m_field##_SHIFT))
@ -844,7 +839,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Dictionary dict;
if (key_type.builtin_type != Variant::NIL || value_type.builtin_type != Variant::NIL) {
dict.set_typed(key_type.builtin_type, key_type.class_name, key_type.script, value_type.builtin_type, value_type.class_name, value_type.script);
dict.set_typed(key_type, value_type);
}
for (int i = 0; i < count; i++) {
@ -901,7 +896,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Array array;
if (type.builtin_type != Variant::NIL) {
array.set_typed(type.builtin_type, type.class_name, type.script);
array.set_typed(type);
}
for (int i = 0; i < count; i++) {
@ -1402,31 +1397,13 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
case Variant::DICTIONARY: {
Dictionary dict = p_variant;
ContainerType key_type;
key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin();
key_type.class_name = dict.get_typed_key_class_name();
key_type.script = dict.get_typed_key_script();
_encode_container_type_header(key_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT, p_full_objects);
ContainerType value_type;
value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin();
value_type.class_name = dict.get_typed_value_class_name();
value_type.script = dict.get_typed_value_script();
_encode_container_type_header(value_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT, p_full_objects);
const Dictionary dict = p_variant;
_encode_container_type_header(dict.get_key_type(), header, HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT, p_full_objects);
_encode_container_type_header(dict.get_value_type(), header, HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT, p_full_objects);
} break;
case Variant::ARRAY: {
Array array = p_variant;
ContainerType type;
type.builtin_type = (Variant::Type)array.get_typed_builtin();
type.class_name = array.get_typed_class_name();
type.script = array.get_typed_script();
_encode_container_type_header(type, header, HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT, p_full_objects);
const Array array = p_variant;
_encode_container_type_header(array.get_element_type(), header, HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT, p_full_objects);
} break;
#ifdef REAL_T_IS_DOUBLE
case Variant::VECTOR2:
@ -1850,27 +1827,17 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 8;
} break;
case Variant::DICTIONARY: {
Dictionary dict = p_variant;
const Dictionary dict = p_variant;
{
ContainerType key_type;
key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin();
key_type.class_name = dict.get_typed_key_class_name();
key_type.script = dict.get_typed_key_script();
Error err = _encode_container_type(key_type, buf, r_len, p_full_objects);
Error err = _encode_container_type(dict.get_key_type(), buf, r_len, p_full_objects);
if (err) {
return err;
}
}
{
ContainerType value_type;
value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin();
value_type.class_name = dict.get_typed_value_class_name();
value_type.script = dict.get_typed_value_script();
Error err = _encode_container_type(value_type, buf, r_len, p_full_objects);
Error err = _encode_container_type(dict.get_value_type(), buf, r_len, p_full_objects);
if (err) {
return err;
}
@ -1894,7 +1861,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (buf) {
buf += len;
}
Variant *value = dict.getptr(key);
const Variant *value = dict.getptr(key);
ERR_FAIL_NULL_V(value, ERR_BUG);
err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
@ -1907,15 +1874,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::ARRAY: {
Array array = p_variant;
const Array array = p_variant;
{
ContainerType type;
type.builtin_type = (Variant::Type)array.get_typed_builtin();
type.class_name = array.get_typed_class_name();
type.script = array.get_typed_script();
Error err = _encode_container_type(type, buf, r_len, p_full_objects);
Error err = _encode_container_type(array.get_element_type(), buf, r_len, p_full_objects);
if (err) {
return err;
}