summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/io/json.cpp86
-rw-r--r--core/io/json.h20
-rw-r--r--core/register_core_types.cpp14
3 files changed, 119 insertions, 1 deletions
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 91500ff3d5..a685fcb718 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -497,6 +497,10 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index,
return ERR_PARSE_ERROR;
}
+void JSON::set_data(const Variant &p_data) {
+ data = p_data;
+}
+
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;
@@ -557,6 +561,88 @@ void JSON::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse", "json_string"), &JSON::parse);
ClassDB::bind_method(D_METHOD("get_data"), &JSON::get_data);
+ ClassDB::bind_method(D_METHOD("set_data", "data"), &JSON::set_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);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), "set_data", "get_data"); // Ensures that it can be serialized as binary.
+}
+
+////
+
+////////////
+
+Ref<Resource> ResourceFormatLoaderJSON::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+ if (r_error) {
+ *r_error = ERR_FILE_CANT_OPEN;
+ }
+
+ if (!FileAccess::exists(p_path)) {
+ *r_error = ERR_FILE_NOT_FOUND;
+ return Ref<Resource>();
+ }
+
+ Ref<JSON> json;
+ json.instantiate();
+
+ Error err = json->parse(FileAccess::get_file_as_string(p_path));
+ if (err != OK) {
+ if (r_error) {
+ *r_error = err;
+ }
+ ERR_PRINT("Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message());
+ return Ref<Resource>();
+ }
+
+ if (r_error) {
+ *r_error = OK;
+ }
+
+ return json;
+}
+
+void ResourceFormatLoaderJSON::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("json");
+}
+
+bool ResourceFormatLoaderJSON::handles_type(const String &p_type) const {
+ return (p_type == "JSON");
+}
+
+String ResourceFormatLoaderJSON::get_resource_type(const String &p_path) const {
+ String el = p_path.get_extension().to_lower();
+ if (el == "json") {
+ return "JSON";
+ }
+ return "";
+}
+
+Error ResourceFormatSaverJSON::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
+ Ref<JSON> json = p_resource;
+ ERR_FAIL_COND_V(json.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = JSON::stringify(json->get_data(), "\t", false, true);
+
+ Error err;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+
+ ERR_FAIL_COND_V_MSG(err, err, "Cannot save json '" + p_path + "'.");
+
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
+
+ return OK;
+}
+
+void ResourceFormatSaverJSON::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
+ Ref<JSON> json = p_resource;
+ if (json.is_valid()) {
+ p_extensions->push_back("json");
+ }
+}
+
+bool ResourceFormatSaverJSON::recognize(const Ref<Resource> &p_resource) const {
+ return p_resource->get_class_name() == "JSON"; //only json, not inherited
}
diff --git a/core/io/json.h b/core/io/json.h
index 840b1cc08a..208d4ad625 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,7 +31,9 @@
#ifndef JSON_H
#define JSON_H
-#include "core/object/ref_counted.h"
+#include "core/io/resource.h"
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
#include "core/variant/variant.h"
class JSON : public RefCounted {
@@ -86,8 +88,24 @@ public:
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; }
};
+class ResourceFormatLoaderJSON : public ResourceFormatLoader {
+public:
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverJSON : public ResourceFormatSaver {
+public:
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const Ref<Resource> &p_resource) const;
+};
+
#endif // JSON_H
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 6650d9be23..6dfb0f82e0 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -87,6 +87,8 @@ static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
+static Ref<ResourceFormatSaverJSON> resource_saver_json;
+static Ref<ResourceFormatLoaderJSON> resource_loader_json;
static core_bind::ResourceLoader *_resource_loader = nullptr;
static core_bind::ResourceSaver *_resource_saver = nullptr;
@@ -211,6 +213,12 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
+ resource_loader_json.instantiate();
+ ResourceLoader::add_resource_format_loader(resource_loader_json);
+
+ resource_saver_json.instantiate();
+ ResourceSaver::add_resource_format_saver(resource_saver_json);
+
GDREGISTER_CLASS(MainLoop);
GDREGISTER_CLASS(Translation);
GDREGISTER_CLASS(OptimizedTranslation);
@@ -387,6 +395,12 @@ void unregister_core_types() {
ResourceLoader::remove_resource_format_loader(resource_format_loader_crypto);
resource_format_loader_crypto.unref();
+ ResourceSaver::remove_resource_format_saver(resource_saver_json);
+ resource_saver_json.unref();
+
+ ResourceLoader::remove_resource_format_loader(resource_loader_json);
+ resource_loader_json.unref();
+
if (ip) {
memdelete(ip);
}