Переглянути джерело

Consolidate JSON, JSONParseResults and JSONParser into JSON

Renames JSON.parse_string() to parse()
Renames JSON.decode_data() to stringify()
Marcel Admiraal 4 роки тому
батько
коміт
2bafcd3422

+ 0 - 75
core/core_bind.cpp

@@ -35,7 +35,6 @@
 #include "core/debugger/engine_debugger.h"
 #include "core/io/file_access_compressed.h"
 #include "core/io/file_access_encrypted.h"
-#include "core/io/json.h"
 #include "core/io/marshalls.h"
 #include "core/math/geometry_2d.h"
 #include "core/math/geometry_3d.h"
@@ -2137,80 +2136,6 @@ void _Engine::_bind_methods() {
 
 _Engine *_Engine::singleton = nullptr;
 
-////// _JSON //////
-
-void JSONParseResult::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("get_error"), &JSONParseResult::get_error);
-	ClassDB::bind_method(D_METHOD("get_error_string"), &JSONParseResult::get_error_string);
-	ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParseResult::get_error_line);
-	ClassDB::bind_method(D_METHOD("get_result"), &JSONParseResult::get_result);
-
-	ClassDB::bind_method(D_METHOD("set_error", "error"), &JSONParseResult::set_error);
-	ClassDB::bind_method(D_METHOD("set_error_string", "error_string"), &JSONParseResult::set_error_string);
-	ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line);
-	ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result);
-
-	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
-	ADD_PROPERTY(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
-	ADD_PROPERTY(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
-}
-
-void JSONParseResult::set_error(Error p_error) {
-	error = p_error;
-}
-
-Error JSONParseResult::get_error() const {
-	return error;
-}
-
-void JSONParseResult::set_error_string(const String &p_error_string) {
-	error_string = p_error_string;
-}
-
-String JSONParseResult::get_error_string() const {
-	return error_string;
-}
-
-void JSONParseResult::set_error_line(int p_error_line) {
-	error_line = p_error_line;
-}
-
-int JSONParseResult::get_error_line() const {
-	return error_line;
-}
-
-void JSONParseResult::set_result(const Variant &p_result) {
-	result = p_result;
-}
-
-Variant JSONParseResult::get_result() const {
-	return result;
-}
-
-void _JSON::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("print", "value", "indent", "sort_keys", "full_precision"), &_JSON::print, DEFVAL(String()), DEFVAL(false), DEFVAL(false));
-	ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse);
-}
-
-String _JSON::print(const Variant &p_value, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
-	return JSON::print(p_value, p_indent, p_sort_keys, p_full_precision);
-}
-
-Ref<JSONParseResult> _JSON::parse(const String &p_json) {
-	Ref<JSONParseResult> result;
-	result.instance();
-
-	result->error = JSON::parse(p_json, result->result, result->error_string, result->error_line);
-
-	if (result->error != OK) {
-		ERR_PRINT(vformat("Error parsing JSON at line %s: %s", result->error_line, result->error_string));
-	}
-	return result;
-}
-
-_JSON *_JSON::singleton = nullptr;
-
 ////// _EngineDebugger //////
 
 void _EngineDebugger::_bind_methods() {

+ 0 - 48
core/core_bind.h

@@ -656,54 +656,6 @@ public:
 	_Engine() { singleton = this; }
 };
 
-class _JSON;
-
-class JSONParseResult : public RefCounted {
-	GDCLASS(JSONParseResult, RefCounted);
-
-	friend class _JSON;
-
-	Error error;
-	String error_string;
-	int error_line = -1;
-
-	Variant result;
-
-protected:
-	static void _bind_methods();
-
-public:
-	void set_error(Error p_error);
-	Error get_error() const;
-
-	void set_error_string(const String &p_error_string);
-	String get_error_string() const;
-
-	void set_error_line(int p_error_line);
-	int get_error_line() const;
-
-	void set_result(const Variant &p_result);
-	Variant get_result() const;
-
-	JSONParseResult() {}
-};
-
-class _JSON : public Object {
-	GDCLASS(_JSON, Object);
-
-protected:
-	static void _bind_methods();
-	static _JSON *singleton;
-
-public:
-	static _JSON *get_singleton() { return singleton; }
-
-	String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false, bool p_full_precision = false);
-	Ref<JSONParseResult> parse(const String &p_json);
-
-	_JSON() { singleton = this; }
-};
-
 class _EngineDebugger : public Object {
 	GDCLASS(_EngineDebugger, Object);
 

+ 21 - 36
core/io/json.cpp

@@ -45,7 +45,7 @@ const char *JSON::tk_name[TK_MAX] = {
 	"EOF",
 };
 
-static String _make_indent(const String &p_indent, int p_size) {
+String JSON::_make_indent(const String &p_indent, int p_size) {
 	String indent_text = "";
 	if (!p_indent.is_empty()) {
 		for (int i = 0; i < p_size; i++) {
@@ -55,7 +55,7 @@ static String _make_indent(const String &p_indent, int p_size) {
 	return indent_text;
 }
 
-String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision) {
+String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision) {
 	String colon = ":";
 	String end_statement = "";
 
@@ -100,7 +100,7 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
 					s += ",";
 					s += end_statement;
 				}
-				s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
+				s += _make_indent(p_indent, p_cur_indent + 1) + _stringify(a[i], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
 			}
 			s += end_statement + _make_indent(p_indent, p_cur_indent) + "]";
 			p_markers.erase(a.id());
@@ -126,9 +126,9 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
 					s += ",";
 					s += end_statement;
 				}
-				s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
+				s += _make_indent(p_indent, p_cur_indent + 1) + _stringify(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
 				s += colon;
-				s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
+				s += _stringify(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
 			}
 
 			s += end_statement + _make_indent(p_indent, p_cur_indent) + "}";
@@ -140,11 +140,6 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
 	}
 }
 
-String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
-	Set<const void *> markers;
-	return _print_var(p_var, p_indent, 0, p_sort_keys, markers, p_full_precision);
-}
-
 Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {
 	while (p_len > 0) {
 		switch (p_str[index]) {
@@ -499,7 +494,7 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index,
 	return ERR_PARSE_ERROR;
 }
 
-Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
+Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
 	const char32_t *str = p_json.ptr();
 	int idx = 0;
 	int len = p_json.length();
@@ -530,34 +525,24 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &
 	return err;
 }
 
-Error JSONParser::parse_string(const String &p_json_string) {
-	return JSON::parse(p_json_string, data, err_text, err_line);
-}
-String JSONParser::get_error_text() const {
-	return err_text;
-}
-int JSONParser::get_error_line() const {
-	return err_line;
-}
-Variant JSONParser::get_data() const {
-	return data;
+String JSON::stringify(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
+	Set<const void *> markers;
+	return _stringify(p_var, p_indent, 0, p_sort_keys, markers, p_full_precision);
 }
 
-Error JSONParser::decode_data(const Variant &p_data, const String &p_indent, bool p_sort_keys) {
-	string = JSON::print(p_data, p_indent, p_sort_keys);
-	data = p_data;
-	return OK;
+Error JSON::parse(const String &p_json_string) {
+	Error err = _parse_string(p_json_string, data, err_str, err_line);
+	if (err == Error::OK) {
+		err_line = 0;
+	}
+	return err;
 }
 
-String JSONParser::get_string() const {
-	return string;
-}
+void JSON::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("stringify", "data", "indent", "sort_keys", "full_precision"), &JSON::stringify, DEFVAL(""), DEFVAL(true), DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("parse", "json_string"), &JSON::parse);
 
-void JSONParser::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("parse_string", "json_string"), &JSONParser::parse_string);
-	ClassDB::bind_method(D_METHOD("get_error_text"), &JSONParser::get_error_text);
-	ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParser::get_error_line);
-	ClassDB::bind_method(D_METHOD("get_data"), &JSONParser::get_data);
-	ClassDB::bind_method(D_METHOD("decode_data", "data", "indent", "sort_keys"), &JSONParser::decode_data, DEFVAL(""), DEFVAL(true));
-	ClassDB::bind_method(D_METHOD("get_string"), &JSONParser::get_string);
+	ClassDB::bind_method(D_METHOD("get_data"), &JSON::get_data);
+	ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line);
+	ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message);
 }

+ 16 - 22
core/io/json.h

@@ -33,7 +33,10 @@
 
 #include "core/object/ref_counted.h"
 #include "core/variant/variant.h"
-class JSON {
+
+class JSON : public RefCounted {
+	GDCLASS(JSON, RefCounted);
+
 	enum TokenType {
 		TK_CURLY_BRACKET_OPEN,
 		TK_CURLY_BRACKET_CLOSE,
@@ -60,39 +63,30 @@ class JSON {
 		Variant value;
 	};
 
-	static const char *tk_name[TK_MAX];
+	Variant data;
+	String err_str;
+	int err_line = 0;
 
-	static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision = false);
+	static const char *tk_name[];
 
+	static String _make_indent(const String &p_indent, int p_size);
+	static String _stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers, bool p_full_precision = false);
 	static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
 	static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
 	static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
 	static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
-
-public:
-	static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false);
-	static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
-};
-
-class JSONParser : public RefCounted {
-	GDCLASS(JSONParser, RefCounted);
-
-	Variant data;
-	String string;
-	String err_text;
-	int err_line = 0;
+	static Error _parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
 
 protected:
 	static void _bind_methods();
 
 public:
-	Error parse_string(const String &p_json_string);
-	String get_error_text() const;
-	int get_error_line() const;
-	Variant get_data() const;
+	String stringify(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false);
+	Error parse(const String &p_json_string);
 
-	Error decode_data(const Variant &p_data, const String &p_indent = "", bool p_sort_keys = true);
-	String get_string() const;
+	inline Variant get_data() const { return data; }
+	inline int get_error_line() const { return err_line; }
+	inline String get_error_message() const { return err_str; }
 };
 
 #endif // JSON_H

+ 1 - 8
core/register_core_types.cpp

@@ -86,7 +86,6 @@ static _OS *_os = nullptr;
 static _Engine *_engine = nullptr;
 static _ClassDB *_classdb = nullptr;
 static _Marshalls *_marshalls = nullptr;
-static _JSON *_json = nullptr;
 static _EngineDebugger *_engine_debugger = nullptr;
 
 static IP *ip = nullptr;
@@ -199,7 +198,7 @@ void register_core_types() {
 	ClassDB::register_class<_Semaphore>();
 
 	ClassDB::register_class<XMLParser>();
-	ClassDB::register_class<JSONParser>();
+	ClassDB::register_class<JSON>();
 
 	ClassDB::register_class<ConfigFile>();
 
@@ -212,8 +211,6 @@ void register_core_types() {
 	ClassDB::register_class<EncodedObjectAsID>();
 	ClassDB::register_class<RandomNumberGenerator>();
 
-	ClassDB::register_class<JSONParseResult>();
-
 	ClassDB::register_virtual_class<ResourceImporter>();
 
 	ip = IP::create();
@@ -227,7 +224,6 @@ void register_core_types() {
 	_engine = memnew(_Engine);
 	_classdb = memnew(_ClassDB);
 	_marshalls = memnew(_Marshalls);
-	_json = memnew(_JSON);
 	_engine_debugger = memnew(_EngineDebugger);
 }
 
@@ -256,7 +252,6 @@ void register_core_singletons() {
 	ClassDB::register_class<TranslationServer>();
 	ClassDB::register_virtual_class<Input>();
 	ClassDB::register_class<InputMap>();
-	ClassDB::register_class<_JSON>();
 	ClassDB::register_class<Expression>();
 	ClassDB::register_class<_EngineDebugger>();
 	ClassDB::register_class<Time>();
@@ -274,7 +269,6 @@ void register_core_singletons() {
 	Engine::get_singleton()->add_singleton(Engine::Singleton("TranslationServer", TranslationServer::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("Input", Input::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
-	Engine::get_singleton()->add_singleton(Engine::Singleton("JSON", _JSON::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
 }
@@ -286,7 +280,6 @@ void unregister_core_types() {
 	memdelete(_engine);
 	memdelete(_classdb);
 	memdelete(_marshalls);
-	memdelete(_json);
 	memdelete(_engine_debugger);
 
 	memdelete(_geometry_2d);

+ 6 - 0
core/variant/variant.cpp

@@ -32,6 +32,7 @@
 
 #include "core/core_string_names.h"
 #include "core/debugger/engine_debugger.h"
+#include "core/io/json.h"
 #include "core/io/marshalls.h"
 #include "core/io/resource.h"
 #include "core/math/math_funcs.h"
@@ -1838,6 +1839,11 @@ String Variant::stringify(List<const void *> &stack) const {
 	return "";
 }
 
+String Variant::to_json_string() const {
+	JSON json;
+	return json.stringify(*this);
+}
+
 Variant::operator Vector2() const {
 	if (type == VECTOR2) {
 		return *reinterpret_cast<const Vector2 *>(_data._mem);

+ 1 - 0
core/variant/variant.h

@@ -645,6 +645,7 @@ public:
 	bool hash_compare(const Variant &p_variant) const;
 	bool booleanize() const;
 	String stringify(List<const void *> &stack) const;
+	String to_json_string() const;
 
 	void static_assign(const Variant &p_variant);
 	static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);

+ 6 - 7
doc/classes/@GlobalScope.xml

@@ -1066,11 +1066,13 @@
 			<description>
 				Returns the internal type of the given Variant object, using the [enum Variant.Type] values.
 				[codeblock]
-				p = parse_json('["a", "b", "c"]')
-				if typeof(p) == TYPE_ARRAY:
-				    print(p[0]) # Prints a
+				var json = JSON.new()
+				json.parse('["a", "b", "c"]')
+				var result = json.get_data()
+				if typeof(result) == TYPE_ARRAY:
+				    print(result[0]) # Prints a
 				else:
-				    print("unexpected results")
+				    print("Unexpected result")
 				[/codeblock]
 			</description>
 		</method>
@@ -1211,9 +1213,6 @@
 		<member name="InputMap" type="InputMap" setter="" getter="">
 			The [InputMap] singleton.
 		</member>
-		<member name="JSON" type="JSON" setter="" getter="">
-			The [JSON] singleton.
-		</member>
 		<member name="JavaClassWrapper" type="JavaClassWrapper" setter="" getter="">
 			The [JavaClassWrapper] singleton.
 			[b]Note:[/b] Only implemented on Android.

+ 56 - 13
doc/classes/JSON.xml

@@ -1,45 +1,88 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSON" inherits="Object" version="4.0">
+<class name="JSON" inherits="RefCounted" version="4.0">
 	<brief_description>
-		Helper class for parsing JSON data.
+		Helper class for creating and parsing JSON data.
 	</brief_description>
 	<description>
-		Helper class for parsing JSON data. For usage example and other important hints, see [JSONParseResult].
+		The [JSON] enables all data types to be converted to and from a JSON string. This useful for serializing data to save to a file or send over the network.
+		[method stringify] is used to convert any data type into a JSON string.
+		[method parse] is used to convert any existing JSON data into a [Variant] that can be used within Godot. If successfully parsed, use [method get_data] to retrieve the [Variant], and use [code]typeof[/code] to check if the Variant's type is what you expect. JSON Objects are converted into a [Dictionary], but JSON data can be used to store [Array]s, numbers, [String]s and even just a boolean.
+		[b]Example[/b]
+		[codeblock]
+		var data_to_send = ["a", "b", "c"]
+		var json = JSON.new()
+		var json_string = json.stringify(data_to_send)
+		# Save data
+		# ...
+		# Retrieve data
+		var error = json.parse(json_string)
+		if error == OK:
+		    var data_received = json.get_data()
+		    if typeof(data_received) == TYPE_ARRAY:
+		        print(data_received) # Prints array
+		    else:
+		        print("Unexpected data")
+		else:
+		    print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
+		[/codeblock]
 	</description>
 	<tutorials>
 	</tutorials>
 	<methods>
+		<method name="get_data" qualifiers="const">
+			<return type="Variant">
+			</return>
+			<description>
+				Returns the [Variant] containing the data of a successful [method parse].
+				[b]Note:[/b] It will return [code]Null[/code] if the last call to parse was unsuccessful or [method parse] has not yet been called.
+			</description>
+		</method>
+		<method name="get_error_line" qualifiers="const">
+			<return type="int">
+			</return>
+			<description>
+				Returns [code]0[/code] if the last call to [method parse] was successful, or the line number where the parse failed.
+			</description>
+		</method>
+		<method name="get_error_message" qualifiers="const">
+			<return type="String">
+			</return>
+			<description>
+				Returns an empty string if the last call to [method parse] was successful, or the error message if it failed.
+			</description>
+		</method>
 		<method name="parse">
-			<return type="JSONParseResult">
+			<return type="int" enum="Error">
 			</return>
-			<argument index="0" name="json" type="String">
+			<argument index="0" name="json_string" type="String">
 			</argument>
 			<description>
-				Parses a JSON-encoded string and returns a [JSONParseResult] containing the result.
+				Attempts to parse the [code]json_string[/code] provided.
+				Returns an [enum Error]. If the parse was successful, it returns [code]OK[/code] and the result can be retrieved using [method get_data]. If unsuccessful, use [method get_error_line] and [method get_error_message] for identifying the source of the failure.
 			</description>
 		</method>
-		<method name="print">
+		<method name="stringify">
 			<return type="String">
 			</return>
-			<argument index="0" name="value" type="Variant">
+			<argument index="0" name="data" type="Variant">
 			</argument>
 			<argument index="1" name="indent" type="String" default="&quot;&quot;">
 			</argument>
-			<argument index="2" name="sort_keys" type="bool" default="false">
+			<argument index="2" name="sort_keys" type="bool" default="true">
 			</argument>
 			<argument index="3" name="full_precision" type="bool" default="false">
 			</argument>
 			<description>
 				Converts a [Variant] var to JSON text and returns the result. Useful for serializing data to store or send over the network.
 				[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, converting a Variant to JSON text will convert all numerical values to [float] types.
-				[b]Note:[/b] If [code]full_precision[/code] is true, when printing floats, the unreliable digits are printed in addition to the reliable digits to guarantee exact decoding.
-				Use [code]indent[/code] parameter to pretty print the output.
+				[b]Note:[/b] If [code]full_precision[/code] is true, when stringifying floats, the unreliable digits are stringified in addition to the reliable digits to guarantee exact decoding.
+				Use [code]indent[/code] parameter to pretty stringify the output.
 				[b]Example output:[/b]
 				[codeblock]
-				## JSON.print(my_dictionary)
+				## JSON.stringify(my_dictionary)
 				{"name":"my_dictionary","version":"1.0.0","entities":[{"name":"entity_0","value":"value_0"},{"name":"entity_1","value":"value_1"}]}
 
-				## JSON.print(my_dictionary, "\t")
+				## JSON.stringify(my_dictionary, "\t")
 				{
 				        "name": "my_dictionary",
 				        "version": "1.0.0",

+ 0 - 51
doc/classes/JSONParseResult.xml

@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSONParseResult" inherits="RefCounted" version="4.0">
-	<brief_description>
-		Data class wrapper for decoded JSON.
-	</brief_description>
-	<description>
-		Returned by [method JSON.parse], [JSONParseResult] contains the decoded JSON or error information if the JSON source wasn't successfully parsed. You can check if the JSON source was successfully parsed with [code]if json_result.error == OK[/code].
-	</description>
-	<tutorials>
-	</tutorials>
-	<methods>
-	</methods>
-	<members>
-		<member name="error" type="int" setter="set_error" getter="get_error" enum="Error">
-			The error type if the JSON source was not successfully parsed. See the [enum Error] constants.
-		</member>
-		<member name="error_line" type="int" setter="set_error_line" getter="get_error_line" default="-1">
-			The line number where the error occurred if the JSON source was not successfully parsed.
-		</member>
-		<member name="error_string" type="String" setter="set_error_string" getter="get_error_string" default="&quot;&quot;">
-			The error message if the JSON source was not successfully parsed. See the [enum Error] constants.
-		</member>
-		<member name="result" type="Variant" setter="set_result" getter="get_result">
-			A [Variant] containing the parsed JSON. Use [method @GlobalScope.typeof] or the [code]is[/code] keyword to check if it is what you expect. For example, if the JSON source starts with curly braces ([code]{}[/code]), a [Dictionary] will be returned. If the JSON source starts with brackets ([code][][/code]), an [Array] will be returned.
-			[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, parsing a JSON text will convert all numerical values to [float] types.
-			[b]Note:[/b] JSON objects do not preserve key order like Godot dictionaries, thus, you should not rely on keys being in a certain order if a dictionary is constructed from JSON. In contrast, JSON arrays retain the order of their elements:
-			[codeblocks]
-			[gdscript]
-			var p = JSON.parse('["hello", "world", "!"]')
-			if typeof(p.result) == TYPE_ARRAY:
-			    print(p.result[0]) # Prints "hello"
-			else:
-			    push_error("Unexpected results.")
-			[/gdscript]
-			[csharp]
-			JSONParseResult p = JSON.Parse("[\"hello\"], \"world\", \"!\"]");
-			if (p.Result is Godot.Collections.Array)
-			{
-			    GD.Print((p.Result as Godot.Collections.Array)[0]); // Prints "hello"
-			}
-			else
-			{
-			    GD.PushError("Unexpected results.");
-			}
-			[/csharp]
-			[/codeblocks]
-		</member>
-	</members>
-	<constants>
-	</constants>
-</class>

+ 0 - 57
doc/classes/JSONParser.xml

@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSONParser" inherits="RefCounted" version="4.0">
-	<brief_description>
-	</brief_description>
-	<description>
-	</description>
-	<tutorials>
-	</tutorials>
-	<methods>
-		<method name="decode_data">
-			<return type="int" enum="Error">
-			</return>
-			<argument index="0" name="data" type="Variant">
-			</argument>
-			<argument index="1" name="indent" type="String" default="&quot;&quot;">
-			</argument>
-			<argument index="2" name="sort_keys" type="bool" default="true">
-			</argument>
-			<description>
-			</description>
-		</method>
-		<method name="get_data" qualifiers="const">
-			<return type="Variant">
-			</return>
-			<description>
-			</description>
-		</method>
-		<method name="get_error_line" qualifiers="const">
-			<return type="int">
-			</return>
-			<description>
-			</description>
-		</method>
-		<method name="get_error_text" qualifiers="const">
-			<return type="String">
-			</return>
-			<description>
-			</description>
-		</method>
-		<method name="get_string" qualifiers="const">
-			<return type="String">
-			</return>
-			<description>
-			</description>
-		</method>
-		<method name="parse_string">
-			<return type="int" enum="Error">
-			</return>
-			<argument index="0" name="json_string" type="String">
-			</argument>
-			<description>
-			</description>
-		</method>
-	</methods>
-	<constants>
-	</constants>
-</class>

+ 21 - 22
editor/editor_feature_profile.cpp

@@ -161,21 +161,21 @@ String EditorFeatureProfile::get_feature_description(Feature p_feature) {
 }
 
 Error EditorFeatureProfile::save_to_file(const String &p_path) {
-	Dictionary json;
-	json["type"] = "feature_profile";
+	Dictionary data;
+	data["type"] = "feature_profile";
 	Array dis_classes;
 	for (Set<StringName>::Element *E = disabled_classes.front(); E; E = E->next()) {
 		dis_classes.push_back(String(E->get()));
 	}
 	dis_classes.sort();
-	json["disabled_classes"] = dis_classes;
+	data["disabled_classes"] = dis_classes;
 
 	Array dis_editors;
 	for (Set<StringName>::Element *E = disabled_editors.front(); E; E = E->next()) {
 		dis_editors.push_back(String(E->get()));
 	}
 	dis_editors.sort();
-	json["disabled_editors"] = dis_editors;
+	data["disabled_editors"] = dis_editors;
 
 	Array dis_props;
 
@@ -185,7 +185,7 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) {
 		}
 	}
 
-	json["disabled_properties"] = dis_props;
+	data["disabled_properties"] = dis_props;
 
 	Array dis_features;
 	for (int i = 0; i < FEATURE_MAX; i++) {
@@ -194,12 +194,13 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) {
 		}
 	}
 
-	json["disabled_features"] = dis_features;
+	data["disabled_features"] = dis_features;
 
 	FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
 	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
 
-	String text = JSON::print(json, "\t");
+	JSON json;
+	String text = json.stringify(data, "\t");
 	f->store_string(text);
 	f->close();
 	return OK;
@@ -212,26 +213,24 @@ Error EditorFeatureProfile::load_from_file(const String &p_path) {
 		return err;
 	}
 
-	String err_str;
-	int err_line;
-	Variant v;
-	err = JSON::parse(text, v, err_str, err_line);
+	JSON json;
+	err = json.parse(text);
 	if (err != OK) {
-		ERR_PRINT("Error parsing '" + p_path + "' on line " + itos(err_line) + ": " + err_str);
+		ERR_PRINT("Error parsing '" + p_path + "' on line " + itos(json.get_error_line()) + ": " + json.get_error_message());
 		return ERR_PARSE_ERROR;
 	}
 
-	Dictionary json = v;
+	Dictionary data = json.get_data();
 
-	if (!json.has("type") || String(json["type"]) != "feature_profile") {
+	if (!data.has("type") || String(data["type"]) != "feature_profile") {
 		ERR_PRINT("Error parsing '" + p_path + "', it's not a feature profile.");
 		return ERR_PARSE_ERROR;
 	}
 
 	disabled_classes.clear();
 
-	if (json.has("disabled_classes")) {
-		Array disabled_classes_arr = json["disabled_classes"];
+	if (data.has("disabled_classes")) {
+		Array disabled_classes_arr = data["disabled_classes"];
 		for (int i = 0; i < disabled_classes_arr.size(); i++) {
 			disabled_classes.insert(disabled_classes_arr[i]);
 		}
@@ -239,8 +238,8 @@ Error EditorFeatureProfile::load_from_file(const String &p_path) {
 
 	disabled_editors.clear();
 
-	if (json.has("disabled_editors")) {
-		Array disabled_editors_arr = json["disabled_editors"];
+	if (data.has("disabled_editors")) {
+		Array disabled_editors_arr = data["disabled_editors"];
 		for (int i = 0; i < disabled_editors_arr.size(); i++) {
 			disabled_editors.insert(disabled_editors_arr[i]);
 		}
@@ -248,16 +247,16 @@ Error EditorFeatureProfile::load_from_file(const String &p_path) {
 
 	disabled_properties.clear();
 
-	if (json.has("disabled_properties")) {
-		Array disabled_properties_arr = json["disabled_properties"];
+	if (data.has("disabled_properties")) {
+		Array disabled_properties_arr = data["disabled_properties"];
 		for (int i = 0; i < disabled_properties_arr.size(); i++) {
 			String s = disabled_properties_arr[i];
 			set_disable_class_property(s.get_slice(":", 0), s.get_slice(":", 1), true);
 		}
 	}
 
-	if (json.has("disabled_features")) {
-		Array disabled_features_arr = json["disabled_features"];
+	if (data.has("disabled_features")) {
+		Array disabled_features_arr = data["disabled_features"];
 		for (int i = 0; i < FEATURE_MAX; i++) {
 			bool found = false;
 			String f = feature_identifiers[i];

+ 3 - 5
editor/export_template_manager.cpp

@@ -242,10 +242,8 @@ void ExportTemplateManager::_refresh_mirrors_completed(int p_status, int p_code,
 		response_json.parse_utf8((const char *)r, p_data.size());
 	}
 
-	Variant response;
-	String errs;
-	int errline;
-	Error err = JSON::parse(response_json, response, errs, errline);
+	JSON json;
+	Error err = json.parse(response_json);
 	if (err != OK) {
 		EditorNode::get_singleton()->show_warning(TTR("Error parsing JSON with the list of mirrors. Please report this issue!"));
 		is_refreshing_mirrors = false;
@@ -260,7 +258,7 @@ void ExportTemplateManager::_refresh_mirrors_completed(int p_status, int p_code,
 
 	mirrors_available = false;
 
-	Dictionary data = response;
+	Dictionary data = json.get_data();
 	if (data.has("mirrors")) {
 		Array mirrors = data["mirrors"];
 

+ 3 - 5
editor/plugins/asset_library_editor_plugin.cpp

@@ -1098,11 +1098,9 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
 
 	Dictionary d;
 	{
-		Variant js;
-		String errs;
-		int errl;
-		JSON::parse(str, js, errs, errl);
-		d = js;
+		JSON json;
+		json.parse(str);
+		d = json.get_data();
 	}
 
 	RequestType requested = requesting;

+ 1 - 2
modules/fbx/tools/validation_tools.h

@@ -34,8 +34,7 @@
 #ifdef TOOLS_ENABLED
 
 #include "core/io/file_access.h"
-#include "core/io/json.h"
-#include "core/string/ustring.h"
+#include "core/string/print_string.h"
 #include "core/templates/local_vector.h"
 #include "core/templates/map.h"
 

+ 4 - 6
modules/gdscript/language_server/gdscript_extend_parser.cpp

@@ -32,7 +32,6 @@
 
 #include "../gdscript.h"
 #include "../gdscript_analyzer.h"
-#include "core/io/json.h"
 #include "gdscript_language_protocol.h"
 #include "gdscript_workspace.h"
 
@@ -183,7 +182,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
 					symbol.detail += ": " + m.get_datatype().to_string();
 				}
 				if (m.variable->initializer != nullptr && m.variable->initializer->is_constant) {
-					symbol.detail += " = " + JSON::print(m.variable->initializer->reduced_value);
+					symbol.detail += " = " + m.variable->initializer->reduced_value.to_json_string();
 				}
 
 				symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.variable->start_line));
@@ -224,10 +223,10 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
 							}
 						}
 					} else {
-						value_text = JSON::print(default_value);
+						value_text = default_value.to_json_string();
 					}
 				} else {
-					value_text = JSON::print(default_value);
+					value_text = default_value.to_json_string();
 				}
 				if (!value_text.is_empty()) {
 					symbol.detail += " = " + value_text;
@@ -353,8 +352,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
 			parameters += ": " + parameter->get_datatype().to_string();
 		}
 		if (parameter->default_value != nullptr) {
-			String value = JSON::print(parameter->default_value->reduced_value);
-			parameters += " = " + value;
+			parameters += " = " + parameter->default_value->reduced_value.to_json_string();
 		}
 	}
 	r_symbol.detail += parameters + ")";

+ 2 - 3
modules/gdscript/language_server/gdscript_language_protocol.cpp

@@ -31,7 +31,6 @@
 #include "gdscript_language_protocol.h"
 
 #include "core/config/project_settings.h"
-#include "core/io/json.h"
 #include "editor/doc_tools.h"
 #include "editor/editor_log.h"
 #include "editor/editor_node.h"
@@ -194,7 +193,7 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
 				vformat("GDScriptLanguageProtocol: Can't initialize invalid peer '%d'.", latest_client_id));
 		Ref<LSPeer> peer = clients.get(latest_client_id);
 		if (peer != nullptr) {
-			String msg = JSON::print(request);
+			String msg = Variant(request).to_json_string();
 			msg = format_output(msg);
 			(*peer)->res_queue.push_back(msg.utf8());
 		}
@@ -280,7 +279,7 @@ void GDScriptLanguageProtocol::notify_client(const String &p_method, const Varia
 	ERR_FAIL_COND(peer == nullptr);
 
 	Dictionary message = make_notification(p_method, p_params);
-	String msg = JSON::print(message);
+	String msg = Variant(message).to_json_string();
 	msg = format_output(msg);
 	peer->res_queue.push_back(msg.utf8());
 }

+ 0 - 1
modules/gltf/editor_scene_importer_gltf.cpp

@@ -30,7 +30,6 @@
 
 #include "core/crypto/crypto_core.h"
 #include "core/io/file_access.h"
-#include "core/io/json.h"
 #include "core/math/disjoint_set.h"
 #include "core/math/math_defs.h"
 #include "core/os/os.h"

+ 0 - 1
modules/gltf/editor_scene_importer_gltf.h

@@ -32,7 +32,6 @@
 #define EDITOR_SCENE_IMPORTER_GLTF_H
 
 #include "core/config/project_settings.h"
-#include "core/io/json.h"
 #include "core/object/object.h"
 #include "core/templates/vector.h"
 #include "editor/import/resource_importer_scene.h"

+ 10 - 14
modules/gltf/gltf_document.cpp

@@ -238,15 +238,13 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
 	String text;
 	text.parse_utf8((const char *)array.ptr(), array.size());
 
-	String err_txt;
-	int err_line;
-	Variant v;
-	err = JSON::parse(text, v, err_txt, err_line);
+	JSON json;
+	err = json.parse(text);
 	if (err != OK) {
-		_err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT);
+		_err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), ERR_HANDLER_SCRIPT);
 		return err;
 	}
-	state->json = v;
+	state->json = json.get_data();
 
 	return OK;
 }
@@ -299,16 +297,14 @@ Error GLTFDocument::_parse_glb(const String &p_path, Ref<GLTFState> state) {
 	String text;
 	text.parse_utf8((const char *)json_data.ptr(), json_data.size());
 
-	String err_txt;
-	int err_line;
-	Variant v;
-	err = JSON::parse(text, v, err_txt, err_line);
+	JSON json;
+	err = json.parse(text);
 	if (err != OK) {
-		_err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT);
+		_err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), ERR_HANDLER_SCRIPT);
 		return err;
 	}
 
-	state->json = v;
+	state->json = json.get_data();
 
 	//data?
 
@@ -6584,7 +6580,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
 		FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 		ERR_FAIL_COND_V(!f, FAILED);
 
-		String json = JSON::print(state->json);
+		String json = Variant(state->json).to_json_string();
 
 		const uint32_t magic = 0x46546C67; // GLTF
 		const int32_t header_size = 12;
@@ -6625,7 +6621,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
 		ERR_FAIL_COND_V(!f, FAILED);
 
 		f->create(FileAccess::ACCESS_RESOURCES);
-		String json = JSON::print(state->json);
+		String json = Variant(state->json).to_json_string();
 		f->store_string(json);
 		f->close();
 	}

+ 6 - 7
modules/jsonrpc/jsonrpc.cpp

@@ -29,6 +29,7 @@
 /*************************************************************************/
 
 #include "jsonrpc.h"
+
 #include "core/io/json.h"
 
 JSONRPC::JSONRPC() {
@@ -156,19 +157,17 @@ String JSONRPC::process_string(const String &p_input) {
 	}
 
 	Variant ret;
-	Variant input;
-	String err_message;
-	int err_line;
-	if (OK != JSON::parse(p_input, input, err_message, err_line)) {
-		ret = make_response_error(JSONRPC::PARSE_ERROR, "Parse error");
+	JSON json;
+	if (json.parse(p_input) == OK) {
+		ret = process_action(json.get_data(), true);
 	} else {
-		ret = process_action(input, true);
+		ret = make_response_error(JSONRPC::PARSE_ERROR, "Parse error");
 	}
 
 	if (ret.get_type() == Variant::NIL) {
 		return "";
 	}
-	return JSON::print(ret);
+	return ret.to_json_string();
 }
 
 void JSONRPC::set_scope(const String &p_scope, Object *p_obj) {

+ 2 - 1
modules/mono/class_db_api_json.cpp

@@ -240,7 +240,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 
 	FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE);
 	ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_output_file + "'.");
-	f->store_string(JSON::print(classes_dict, /*indent: */ "\t"));
+	JSON json;
+	f->store_string(json.stringify(classes_dict, "\t"));
 	f->close();
 
 	print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file));

+ 0 - 1
modules/mono/csharp_script.cpp

@@ -38,7 +38,6 @@
 #include "core/debugger/engine_debugger.h"
 #include "core/debugger/script_debugger.h"
 #include "core/io/file_access.h"
-#include "core/io/json.h"
 #include "core/os/mutex.h"
 #include "core/os/os.h"
 #include "core/os/thread.h"

+ 4 - 5
platform/javascript/export/export.cpp

@@ -29,7 +29,6 @@
 /*************************************************************************/
 
 #include "core/io/image_loader.h"
-#include "core/io/json.h"
 #include "core/io/stream_peer_ssl.h"
 #include "core/io/tcp_server.h"
 #include "core/io/zip_io.h"
@@ -465,7 +464,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
 	}
 
 	// Replaces HTML string
-	const String str_config = JSON::print(config);
+	const String str_config = Variant(config).to_json_string();
 	const String custom_head_include = p_preset->get("html/head_include");
 	Map<String, String> replaces;
 	replaces["$GODOT_URL"] = p_name + ".js";
@@ -518,7 +517,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
 	replaces["@GODOT_NAME@"] = name;
 	replaces["@GODOT_OFFLINE_PAGE@"] = name + ".offline.html";
 	Array files;
-	replaces["@GODOT_OPT_CACHE@"] = JSON::print(files);
+	replaces["@GODOT_OPT_CACHE@"] = Variant(files).to_json_string();
 	files.push_back(name + ".html");
 	files.push_back(name + ".js");
 	files.push_back(name + ".wasm");
@@ -537,7 +536,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
 			files.push_back(p_shared_objects[i].path.get_file());
 		}
 	}
-	replaces["@GODOT_CACHE@"] = JSON::print(files);
+	replaces["@GODOT_CACHE@"] = Variant(files).to_json_string();
 
 	const String sw_path = dir.plus_file(name + ".service.worker.js");
 	Vector<uint8_t> sw;
@@ -605,7 +604,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
 	}
 	manifest["icons"] = icons_arr;
 
-	CharString cs = JSON::print(manifest).utf8();
+	CharString cs = Variant(manifest).to_json_string().utf8();
 	err = _write_or_error((const uint8_t *)cs.get_data(), cs.length(), dir.plus_file(name + ".manifest.json"));
 	if (err != OK) {
 		return err;

+ 23 - 38
tests/test_json.h

@@ -45,75 +45,65 @@ TEST_CASE("[JSON] Parsing single data types") {
 	// Parsing a single data type as JSON is valid per the JSON specification.
 
 	JSON json;
-	Variant result;
-	String err_str;
-	int err_line;
 
-	json.parse("null", result, err_str, err_line);
+	json.parse("null");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing `null` as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			result == Variant(),
+			json.get_data() == Variant(),
 			"Parsing a double quoted string as JSON should return the expected value.");
 
-	json.parse("true", result, err_str, err_line);
+	json.parse("true");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing boolean `true` as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			result,
+			json.get_data(),
 			"Parsing boolean `true` as JSON should return the expected value.");
 
-	json.parse("false", result, err_str, err_line);
+	json.parse("false");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing boolean `false` as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			!result,
+			!json.get_data(),
 			"Parsing boolean `false` as JSON should return the expected value.");
 
-	// JSON only has a floating-point number type, no integer type.
-	// This is why we use `is_equal_approx()` for the comparison.
-	json.parse("123456", result, err_str, err_line);
+	json.parse("123456");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing an integer number as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			(int)result == 123'456,
+			(int)(json.get_data()) == 123456,
 			"Parsing an integer number as JSON should return the expected value.");
 
-	json.parse("0.123456", result, err_str, err_line);
+	json.parse("0.123456");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing a floating-point number as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			Math::is_equal_approx(result, 0.123456),
+			Math::is_equal_approx(json.get_data(), 0.123456),
 			"Parsing a floating-point number as JSON should return the expected value.");
 
-	json.parse("\"hello\"", result, err_str, err_line);
+	json.parse("\"hello\"");
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing a double quoted string as JSON should parse successfully.");
 	CHECK_MESSAGE(
-			result == "hello",
+			json.get_data() == "hello",
 			"Parsing a double quoted string as JSON should return the expected value.");
 }
 
 TEST_CASE("[JSON] Parsing arrays") {
 	JSON json;
-	Variant result;
-	String err_str;
-	int err_line;
 
 	// JSON parsing fails if it's split over several lines (even if leading indentation is removed).
-	json.parse(
-			R"(["Hello", "world.", "This is",["a","json","array.",[]], "Empty arrays ahoy:", [[["Gotcha!"]]]])",
-			result, err_str, err_line);
+	json.parse(R"(["Hello", "world.", "This is",["a","json","array.",[]], "Empty arrays ahoy:", [[["Gotcha!"]]]])");
 
-	const Array array = result;
+	const Array array = json.get_data();
 	CHECK_MESSAGE(
-			err_line == 0,
+			json.get_error_line() == 0,
 			"Parsing a JSON array should parse successfully.");
 	CHECK_MESSAGE(
 			array[0] == "Hello",
@@ -136,15 +126,10 @@ TEST_CASE("[JSON] Parsing arrays") {
 
 TEST_CASE("[JSON] Parsing objects (dictionaries)") {
 	JSON json;
-	Variant result;
-	String err_str;
-	int err_line;
 
-	json.parse(
-			R"({"name": "Godot Engine", "is_free": true, "bugs": null, "apples": {"red": 500, "green": 0, "blue": -20}, "empty_object": {}})",
-			result, err_str, err_line);
+	json.parse(R"({"name": "Godot Engine", "is_free": true, "bugs": null, "apples": {"red": 500, "green": 0, "blue": -20}, "empty_object": {}})");
 
-	const Dictionary dictionary = result;
+	const Dictionary dictionary = json.get_data();
 	CHECK_MESSAGE(
 			dictionary["name"] == "Godot Engine",
 			"The parsed JSON should contain the expected values.");