diff --git a/libs/internal/src/serialization/json_evaluation_result.cpp b/libs/internal/src/serialization/json_evaluation_result.cpp index 7b7b8a335..6583cc70f 100644 --- a/libs/internal/src/serialization/json_evaluation_result.cpp +++ b/libs/internal/src/serialization/json_evaluation_result.cpp @@ -8,7 +8,6 @@ #include namespace launchdarkly { - tl::expected, JsonError> tag_invoke( boost::json::value_to_tag< tl::expected, JsonError>> const& unused, @@ -56,15 +55,22 @@ tl::expected, JsonError> tag_invoke( // when deserializing FlagMeta. Primarily `variation` not // `variationIndex`. - auto* value_iter = json_obj.find("value"); - if (value_iter == json_obj.end()) { - return tl::unexpected(JsonError::kSchemaFailure); - } - - auto maybe_value = boost::json::value_to>( - value_iter->value()); - if (!maybe_value) { - return tl::unexpected(maybe_value.error()); + // todo(cwaldren): SC-203949 + SC-236165 + // We're looking for the evaluated value. If it's not there, we should treat + // it as null and *not* a schema error. This is because the server-side SDK + // that produced the EvaluationResult may have omitted the 'null' value. + // Otherwise, if it is there, it must deserialize to a valid Value (which + // might itself be null.) + Value value = Value::Null(); + if (auto* value_iter = json_obj.find("value"); + value_iter != json_obj.end()) { + auto maybe_value = + boost::json::value_to>( + value_iter->value()); + if (!maybe_value) { + return tl::unexpected(maybe_value.error()); + } + value = *maybe_value; } auto* variation_iter = json_obj.find("variation"); @@ -85,7 +91,7 @@ tl::expected, JsonError> tag_invoke( track_events, track_reason, debug_events_until_date, - EvaluationDetailInternal(*maybe_value, variation, + EvaluationDetailInternal(std::move(value), variation, std::make_optional(reason.value()))}; } // We could not parse the reason. @@ -99,7 +105,7 @@ tl::expected, JsonError> tag_invoke( track_events, track_reason, debug_events_until_date, - EvaluationDetailInternal(*maybe_value, variation, std::nullopt)}; + EvaluationDetailInternal(std::move(value), variation, std::nullopt)}; } void tag_invoke(boost::json::value_from_tag const& unused, @@ -127,7 +133,7 @@ void tag_invoke(boost::json::value_from_tag const& unused, "debugEventsUntilDate", std::chrono::duration_cast( evaluation_result.DebugEventsUntilDate()->time_since_epoch()) - .count()); + .count()); } auto& detail = evaluation_result.Detail(); @@ -143,5 +149,4 @@ void tag_invoke(boost::json::value_from_tag const& unused, obj.emplace("reason", reason_json); } } - -} // namespace launchdarkly +} // namespace launchdarkly