Skip to content
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package com.octopus.openfeature.provider;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@JsonIgnoreProperties(ignoreUnknown = true)
class FeatureToggleEvaluation {
private final String name;
private final String slug;
private final boolean isEnabled;
private final List<Map.Entry<String, String>> segments;

@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
FeatureToggleEvaluation(@JsonProperty("name") String name, @JsonProperty("slug")String slug, @JsonProperty("isEnabled") boolean isEnabled,
@JsonProperty("segments") List<Map.Entry<String, String>> segments) {
FeatureToggleEvaluation(
@JsonProperty("name") String name,
@JsonProperty("slug") String slug,
@JsonProperty("isEnabled") boolean isEnabled,
@JsonDeserialize(contentUsing = SegmentDeserializer.class) @JsonProperty("segments") List<Map.Entry<String, String>> segments
) {
this.name = name;
this.slug = slug;
this.isEnabled = isEnabled;

this.segments = new ArrayList<>();
if (segments != null) {
this.segments.addAll(segments);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.octopus.openfeature.provider;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;
import java.util.AbstractMap;
import java.util.Map;

class SegmentDeserializer extends JsonDeserializer<Map.Entry<String, String>> {
@Override
public Map.Entry<String, String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
String key = node.get("key").asText();
String value = node.get("value").asText();
Comment thread
liamhughes marked this conversation as resolved.
Outdated
return new AbstractMap.SimpleEntry<>(key, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.octopus.openfeature.provider;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.util.List;
import java.util.Map;
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import java.util.Map can be removed to keep the test focused and avoid IDE/linter noise.

Suggested change
import java.util.Map;

Copilot uses AI. Check for mistakes.

import static org.assertj.core.api.Assertions.assertThat;

class FeatureToggleEvaluationDeserializationTests {

private final ObjectMapper objectMapper = new ObjectMapper();

private InputStream resource(String name) {
return getClass().getResourceAsStream(name);
}

@Test
void shouldDeserializeEnabledToggle() throws Exception {
FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-enabled-no-segments.json"), FeatureToggleEvaluation.class);

assertThat(result.getName()).isEqualTo("My Feature");
assertThat(result.getSlug()).isEqualTo("my-feature");
assertThat(result.isEnabled()).isTrue();
assertThat(result.getSegments()).isEmpty();
}

@Test
void shouldDeserializeDisabledToggle() throws Exception {
FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-disabled.json"), FeatureToggleEvaluation.class);

assertThat(result.isEnabled()).isFalse();
}

@Test
void shouldDeserializeToggleWithMissingSegmentsField() throws Exception {
FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-missing-segments.json"), FeatureToggleEvaluation.class);

assertThat(result.getSegments()).isNotNull().isEmpty();
}

@Test
void shouldDeserializeToggleWithSegments() throws Exception {
FeatureToggleEvaluation result = objectMapper.readValue(
resource("toggle-with-segments.json"), FeatureToggleEvaluation.class);

assertThat(result.getSegments()).hasSize(2);
assertThat(result.getSegments()).contains(
Map.entry("license-type", "free"),
Map.entry("country", "au")
);
}

@Test
void shouldDeserializeListOfToggles() throws Exception {
List<FeatureToggleEvaluation> result = objectMapper.readValue(
resource("toggle-list.json"),
new TypeReference<>() {
}
);

assertThat(result).hasSize(2);
assertThat(result.get(0).getSlug()).isEqualTo("feature-a");
assertThat(result.get(0).isEnabled()).isTrue();
assertThat(result.get(1).getSlug()).isEqualTo("feature-b");
assertThat(result.get(1).isEnabled()).isFalse();
}

@Test
void shouldIgnoreExtraneousProperties() throws Exception {
FeatureToggleEvaluation result = objectMapper.readValue(
resource("toggle-with-extraneous-properties.json"), FeatureToggleEvaluation.class);

assertThat(result.getName()).isEqualTo("My Feature");
assertThat(result.getSlug()).isEqualTo("my-feature");
assertThat(result.isEnabled()).isTrue();
assertThat(result.getSegments()).contains(Map.entry("license-type", "free"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "My Feature",
"slug": "my-feature",
"isEnabled": false,
"segments": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "My Feature",
"slug": "my-feature",
"isEnabled": true,
"segments": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"name": "Feature A",
"slug": "feature-a",
"isEnabled": true,
"segments": null
},
{
"name": "Feature B",
"slug": "feature-b",
"isEnabled": false,
"segments": null
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "My Feature",
"slug": "my-feature",
"isEnabled": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "My Feature",
"slug": "my-feature",
"isEnabled": true,
"segments": [
{
"key": "license-type",
"value": "free",
"more": "data"
}
],
"foo": "bar",
"qux": 123,
"wux": {
"nested": "value"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "My Feature",
"slug": "my-feature",
"isEnabled": true,
"segments": [
{
"key": "license-type",
"value": "free"
},
{
"key": "country",
"value": "au"
}
]
}
Loading