1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Use num_scientific (Grisu2) when stringifying JSON with full precision

This commit is contained in:
Aaron Franke
2025-07-21 08:27:21 -07:00
parent 1ce3101fbc
commit a238af4d20
3 changed files with 30 additions and 23 deletions

View File

@@ -82,11 +82,18 @@ void JSON::_stringify(String &r_result, const Variant &p_var, const String &p_in
return; return;
} }
const double magnitude = std::log10(Math::abs(num)); if (p_full_precision) {
const int total_digits = p_full_precision ? 17 : 14; const String num_sci = String::num_scientific(num);
const int precision = MAX(1, total_digits - (int)Math::floor(magnitude)); if (num_sci.contains_char('.') || num_sci.contains_char('e')) {
r_result += num_sci;
r_result += String::num(num, precision); } 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; return;
} }
case Variant::PACKED_INT32_ARRAY: case Variant::PACKED_INT32_ARRAY:

View File

@@ -8423,7 +8423,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path)
constexpr uint32_t text_chunk_type = 0x4E4F534A; // The byte sequence "JSON" as little-endian. 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. 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(); CharString cs = json_string.utf8();
uint64_t text_data_length = cs.length(); uint64_t text_data_length = cs.length();
uint64_t text_chunk_length = ((text_data_length + 3) & (~3)); uint64_t text_chunk_length = ((text_data_length + 3) & (~3));
@@ -8440,7 +8440,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path)
err = _encode_buffer_bins(p_state, p_path); err = _encode_buffer_bins(p_state, p_path);
ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(err != OK, err);
// Since the buffer bins were re-encoded, we need to re-convert the JSON to string. // 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(); cs = json_string.utf8();
text_data_length = cs.length(); text_data_length = cs.length();
text_chunk_length = ((text_data_length + 3) & (~3)); text_chunk_length = ((text_data_length + 3) & (~3));
@@ -8483,7 +8483,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path)
ERR_FAIL_COND_V(file.is_null(), FAILED); ERR_FAIL_COND_V(file.is_null(), FAILED);
file->create(FileAccess::ACCESS_RESOURCES); 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); file->store_string(json);
} }
return err; return err;
@@ -8617,7 +8617,7 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Erro
*r_err = err; *r_err = err;
} }
ERR_FAIL_COND_V(err != OK, PackedByteArray()); 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 header_size = 12;
constexpr uint64_t chunk_header_size = 8; constexpr uint64_t chunk_header_size = 8;

View File

@@ -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]"); 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; Array full_precision_array;
full_precision_array.push_back(0.123456789012345677); full_precision_array.push_back(0.12345678901234568);
CHECK(JSON::stringify(full_precision_array, "", true, true) == "[0.123456789012345677]"); CHECK(JSON::stringify(full_precision_array, "", true, true) == "[0.12345678901234568]");
ERR_PRINT_OFF ERR_PRINT_OFF
Array self_array; Array self_array;
@@ -110,8 +110,8 @@ TEST_CASE("[JSON] Stringify dictionaries") {
CHECK(JSON::stringify(outer) == "{\"inner\":{\"key\":\"value\"}}"); CHECK(JSON::stringify(outer) == "{\"inner\":{\"key\":\"value\"}}");
Dictionary full_precision_dictionary; Dictionary full_precision_dictionary;
full_precision_dictionary["key"] = 0.123456789012345677; full_precision_dictionary["key"] = 0.12345678901234568;
CHECK(JSON::stringify(full_precision_dictionary, "", true, true) == "{\"key\":0.123456789012345677}"); CHECK(JSON::stringify(full_precision_dictionary, "", true, true) == "{\"key\":0.12345678901234568}");
ERR_PRINT_OFF ERR_PRINT_OFF
Dictionary self_dictionary; Dictionary self_dictionary;
@@ -352,16 +352,16 @@ TEST_CASE("[JSON] Serialization") {
static FpTestCase fp_tests_full_precision[] = { static FpTestCase fp_tests_full_precision[] = {
{ 0.0, "0.0" }, { 0.0, "0.0" },
{ 1000.1234567890123456789, "1000.12345678901238" }, { 1000.1234567890123456789, "1000.1234567890124" },
{ -1000.1234567890123456789, "-1000.12345678901238" }, { -1000.1234567890123456789, "-1000.1234567890124" },
{ DBL_MAX, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" }, { DBL_MAX, "1.7976931348623157e+308" },
{ DBL_MAX - 1, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0" }, { DBL_MAX - 1, "1.7976931348623157e+308" },
{ std::pow(2, 53), "9007199254740992.0" }, { std::pow(2, 53), "9.007199254740992e+15" },
{ -std::pow(2, 53), "-9007199254740992.0" }, { -std::pow(2, 53), "-9.007199254740992e+15" },
{ 0.00000000000000011, "0.00000000000000011" }, { 0.00000000000000011, "1.1e-16" },
{ -0.00000000000000011, "-0.00000000000000011" }, { -0.00000000000000011, "-1.1e-16" },
{ 1.0 / 3.0, "0.333333333333333315" }, { 1.0 / 3.0, "0.3333333333333333" },
{ 0.9999999999999999, "0.999999999999999889" }, { 0.9999999999999999, "0.9999999999999999" },
{ 1.0000000000000001, "1.0" }, { 1.0000000000000001, "1.0" },
}; };