diff --git a/core/io/json.cpp b/core/io/json.cpp index 34f001a2282..872d7e67452 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -82,11 +82,18 @@ void JSON::_stringify(String &r_result, const Variant &p_var, const String &p_in return; } - const double magnitude = std::log10(Math::abs(num)); - const int total_digits = p_full_precision ? 17 : 14; - const int precision = MAX(1, total_digits - (int)Math::floor(magnitude)); - - r_result += String::num(num, precision); + if (p_full_precision) { + const String num_sci = String::num_scientific(num); + if (num_sci.contains_char('.') || num_sci.contains_char('e')) { + r_result += num_sci; + } else { + r_result += num_sci + ".0"; + } + } else { + const double magnitude = std::log10(Math::abs(num)); + const int precision = MAX(1, 14 - (int)Math::floor(magnitude)); + r_result += String::num(num, precision); + } return; } case Variant::PACKED_INT32_ARRAY: diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index c807f10550b..9142d60ca38 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -8423,7 +8423,7 @@ Error GLTFDocument::_serialize_file(Ref p_state, const String p_path) constexpr uint32_t text_chunk_type = 0x4E4F534A; // The byte sequence "JSON" as little-endian. constexpr uint32_t binary_chunk_type = 0x004E4942; // The byte sequence "BIN\0" as little-endian. - String json_string = Variant(p_state->json).to_json_string(); + String json_string = JSON::stringify(p_state->json, "", true, true); CharString cs = json_string.utf8(); uint64_t text_data_length = cs.length(); uint64_t text_chunk_length = ((text_data_length + 3) & (~3)); @@ -8440,7 +8440,7 @@ Error GLTFDocument::_serialize_file(Ref p_state, const String p_path) err = _encode_buffer_bins(p_state, p_path); ERR_FAIL_COND_V(err != OK, err); // Since the buffer bins were re-encoded, we need to re-convert the JSON to string. - json_string = Variant(p_state->json).to_json_string(); + json_string = JSON::stringify(p_state->json, "", true, true); cs = json_string.utf8(); text_data_length = cs.length(); text_chunk_length = ((text_data_length + 3) & (~3)); @@ -8483,7 +8483,7 @@ Error GLTFDocument::_serialize_file(Ref p_state, const String p_path) ERR_FAIL_COND_V(file.is_null(), FAILED); file->create(FileAccess::ACCESS_RESOURCES); - String json = Variant(p_state->json).to_json_string(); + String json = JSON::stringify(p_state->json, "", true, true); file->store_string(json); } return err; @@ -8617,7 +8617,7 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref p_state, Erro *r_err = err; } ERR_FAIL_COND_V(err != OK, PackedByteArray()); - String json_string = Variant(p_state->json).to_json_string(); + String json_string = JSON::stringify(p_state->json, "", true, true); constexpr uint64_t header_size = 12; constexpr uint64_t chunk_header_size = 8; diff --git a/tests/core/io/test_json.h b/tests/core/io/test_json.h index 3da156c7681..5a202b4f1ae 100644 --- a/tests/core/io/test_json.h +++ b/tests/core/io/test_json.h @@ -72,8 +72,8 @@ TEST_CASE("[JSON] Stringify arrays") { CHECK(JSON::stringify(indented_array, "\t") == "[\n\t0,\n\t1,\n\t2,\n\t3,\n\t4,\n\t[\n\t\t0,\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t]\n]"); Array full_precision_array; - full_precision_array.push_back(0.123456789012345677); - CHECK(JSON::stringify(full_precision_array, "", true, true) == "[0.123456789012345677]"); + full_precision_array.push_back(0.12345678901234568); + CHECK(JSON::stringify(full_precision_array, "", true, true) == "[0.12345678901234568]"); ERR_PRINT_OFF Array self_array; @@ -110,8 +110,8 @@ TEST_CASE("[JSON] Stringify dictionaries") { CHECK(JSON::stringify(outer) == "{\"inner\":{\"key\":\"value\"}}"); Dictionary full_precision_dictionary; - full_precision_dictionary["key"] = 0.123456789012345677; - CHECK(JSON::stringify(full_precision_dictionary, "", true, true) == "{\"key\":0.123456789012345677}"); + full_precision_dictionary["key"] = 0.12345678901234568; + CHECK(JSON::stringify(full_precision_dictionary, "", true, true) == "{\"key\":0.12345678901234568}"); ERR_PRINT_OFF Dictionary self_dictionary; @@ -352,16 +352,16 @@ TEST_CASE("[JSON] Serialization") { static FpTestCase fp_tests_full_precision[] = { { 0.0, "0.0" }, - { 1000.1234567890123456789, "1000.12345678901238" }, - { -1000.1234567890123456789, "-1000.12345678901238" }, - { DBL_MAX, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" }, - { DBL_MAX - 1, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" }, - { std::pow(2, 53), "9007199254740992.0" }, - { -std::pow(2, 53), "-9007199254740992.0" }, - { 0.00000000000000011, "0.00000000000000011" }, - { -0.00000000000000011, "-0.00000000000000011" }, - { 1.0 / 3.0, "0.333333333333333315" }, - { 0.9999999999999999, "0.999999999999999889" }, + { 1000.1234567890123456789, "1000.1234567890124" }, + { -1000.1234567890123456789, "-1000.1234567890124" }, + { DBL_MAX, "1.7976931348623157e+308" }, + { DBL_MAX - 1, "1.7976931348623157e+308" }, + { std::pow(2, 53), "9.007199254740992e+15" }, + { -std::pow(2, 53), "-9.007199254740992e+15" }, + { 0.00000000000000011, "1.1e-16" }, + { -0.00000000000000011, "-1.1e-16" }, + { 1.0 / 3.0, "0.3333333333333333" }, + { 0.9999999999999999, "0.9999999999999999" }, { 1.0000000000000001, "1.0" }, };