diff --git a/google/cloud/bigquery/v2/minimal/internal/json_utils.h b/google/cloud/bigquery/v2/minimal/internal/json_utils.h index 6917b3a24265d..194b74ac7fff1 100644 --- a/google/cloud/bigquery/v2/minimal/internal/json_utils.h +++ b/google/cloud/bigquery/v2/minimal/internal/json_utils.h @@ -101,7 +101,20 @@ bool SafeGetToWithNullable(ResponseType& value, bool& is_null, if (i != j.end()) { // BQ sends null type values which crashes get_to() so check for null. if (!i->is_null()) { - i->get_to(value); + // JSON value for the field, from the server, can be anything. + // In 80% cases its a string value at which point we retrieve + // the string value. + // For any other values, (like nested Arrays or objects) we just give back + // a string to be parsed by the caller. The library has no idea what to + // expect in the value field it can be anything based on what the client + // sends hence its not feasible to parse here. This is best done on the + // client side based on the client-usecase and column schema returned by + // the server for each of these values. + if (i->type() == nlohmann::json::value_t::string) { + i->get_to(value); + } else { + value = i->dump(); + } } else { is_null = true; } diff --git a/google/cloud/bigquery/v2/minimal/internal/json_utils_test.cc b/google/cloud/bigquery/v2/minimal/internal/json_utils_test.cc index d2282239efe52..29ebf329d89af 100644 --- a/google/cloud/bigquery/v2/minimal/internal/json_utils_test.cc +++ b/google/cloud/bigquery/v2/minimal/internal/json_utils_test.cc @@ -277,6 +277,57 @@ TEST(JsonUtilsTest, SafeGetToWithNullableNonNull) { EXPECT_FALSE(is_null); } +TEST(JsonUtilsTest, SafeGetToWithNullableString) { + auto const* const key = "v"; + auto constexpr kJsonText = R"({"v":"Apple"})"; + auto json = nlohmann::json::parse(kJsonText, nullptr, false); + EXPECT_TRUE(json.is_object()); + + std::string val; + bool is_null; + EXPECT_TRUE(SafeGetToWithNullable(val, is_null, json, key)); + EXPECT_EQ(val, "Apple"); +} + +TEST(JsonUtilsTest, SafeGetToWithNullableStringAsNumber) { + auto const* const key = "v"; + auto constexpr kJsonText = R"({"v":"123"})"; + auto json = nlohmann::json::parse(kJsonText, nullptr, false); + EXPECT_TRUE(json.is_object()); + + std::string val; + bool is_null; + EXPECT_TRUE(SafeGetToWithNullable(val, is_null, json, key)); + EXPECT_EQ(val, "123"); +} + +TEST(JsonUtilsTest, SafeGetToWithNullableStringAsFloat) { + auto const* const key = "v"; + auto constexpr kJsonText = R"({"v":"123.123"})"; + auto json = nlohmann::json::parse(kJsonText, nullptr, false); + EXPECT_TRUE(json.is_object()); + + std::string val; + bool is_null; + EXPECT_TRUE(SafeGetToWithNullable(val, is_null, json, key)); + EXPECT_EQ(val, "123.123"); +} + +TEST(JsonUtilsTest, SafeGetToWithNullableStringAsArray) { + auto const* const key = "v"; + auto constexpr kExpectedJsonText = + R"([{"v":"1"},{"v":"2"},{"v":"3"},{"v":"4"},{"v":"5"}])"; + auto constexpr kJsonText = + R"({"v":[{"v":"1"},{"v":"2"},{"v":"3"},{"v":"4"},{"v":"5"}]})"; + auto json = nlohmann::json::parse(kJsonText, nullptr, false); + EXPECT_TRUE(json.is_object()); + + std::string val; + bool is_null; + EXPECT_TRUE(SafeGetToWithNullable(val, is_null, json, key)); + EXPECT_EQ(val, kExpectedJsonText); +} + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace bigquery_v2_minimal_internal } // namespace cloud