Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Optional Property #151

Merged
merged 2 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.sdk.growthbook.model.GBExperimentResult
import com.sdk.growthbook.model.GBFeature
import com.sdk.growthbook.model.GBFeatureResult
import com.sdk.growthbook.model.GBFeatureSource
import com.sdk.growthbook.utils.OptionalProperty
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject

Expand Down Expand Up @@ -161,7 +162,7 @@ internal class GBFeatureEvaluator {
/**
* Feature value is being forced
*/
if (rule.force != null) {
if (rule.force is OptionalProperty.Present) {

/**
* If it's a conditional rule, skip if the condition doesn't pass
Expand Down Expand Up @@ -240,7 +241,7 @@ internal class GBFeatureEvaluator {
}
val forcedFeatureResult =
prepareResult(
value = rule.force,
value = rule.force.value,
source = GBFeatureSource.force
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.sdk.growthbook.utils.GBFilter
import com.sdk.growthbook.utils.GBTrackData
import com.sdk.growthbook.utils.GBVariationMeta
import com.sdk.growthbook.utils.GBParentConditionInterface
import com.sdk.growthbook.utils.OptionalProperty
import com.sdk.growthbook.utils.OptionalPropertySerializer
import com.sdk.growthbook.utils.RangeSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
Expand Down Expand Up @@ -57,8 +59,8 @@ data class GBFeatureRule(
/**
* Immediately force a specific value (ignore every other option besides condition and coverage)
*/
val force: JsonElement? = null,

@Serializable(with = OptionalPropertySerializer::class)
val force: OptionalProperty<JsonElement?> = OptionalProperty.NotPresent,
/**
* Run an experiment (A/B test) and randomly choose between these variations
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.sdk.growthbook.model.GBFeature
import com.sdk.growthbook.model.GBFeatureResult
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.PairSerializer
import kotlinx.serialization.builtins.serializer
Expand Down Expand Up @@ -313,3 +314,34 @@ object RangeSerializer {
}
}
}

/**
* Wrapper for deserialized model with optional field
*/
sealed class OptionalProperty<out T> {
object NotPresent : OptionalProperty<Nothing>()
data class Present<T>(val value: T) : OptionalProperty<T>()
}

/**
* Serializer for optional properties
*/
open class OptionalPropertySerializer<T>(
private val valueSerializer: KSerializer<T>
) : KSerializer<OptionalProperty<T>> {
final override val descriptor: SerialDescriptor = valueSerializer.descriptor

final override fun deserialize(decoder: Decoder): OptionalProperty<T> =
OptionalProperty.Present(valueSerializer.deserialize(decoder))

final override fun serialize(encoder: Encoder, value: OptionalProperty<T>) {
when (value) {
OptionalProperty.NotPresent -> throw SerializationException(
"Tried to serialize an optional property that had no value present." +
" Is encodeDefaults false?"
)
is OptionalProperty.Present ->
valueSerializer.serialize(encoder, value.value)
}
}
}
Loading