diff --git a/pom.xml b/pom.xml
index d355560..d839f8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
cloud.eppo
eppo-server-sdk
- 2.0.2
+ 2.1.0
${project.groupId}:${project.artifactId}
Eppo Server-Side SDK for Java
diff --git a/src/main/java/com/eppo/sdk/EppoClient.java b/src/main/java/com/eppo/sdk/EppoClient.java
index fc5a4f0..db146a2 100644
--- a/src/main/java/com/eppo/sdk/EppoClient.java
+++ b/src/main/java/com/eppo/sdk/EppoClient.java
@@ -22,6 +22,7 @@
import com.eppo.sdk.helpers.InputValidator;
import com.eppo.sdk.helpers.RuleValidator;
import com.eppo.sdk.helpers.Shard;
+import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
@@ -60,8 +61,7 @@ private EppoClient(ConfigurationStore configurationStore, Timer poller, EppoClie
private Optional getAssignmentValue(
String subjectKey,
String flagKey,
- SubjectAttributes subjectAttributes
- ) {
+ SubjectAttributes subjectAttributes) {
// Validate Input Values
InputValidator.validateNotBlank(subjectKey, "Invalid argument: subjectKey cannot be blank");
InputValidator.validateNotBlank(flagKey, "Invalid argument: flagKey cannot be blank");
@@ -142,6 +142,8 @@ private Optional> getTypedAssignment(String subjectKey, String experimentKey,
return Optional.of(value.get().boolValue());
case NUMBER:
return Optional.of(value.get().doubleValue());
+ case JSON_NODE:
+ return Optional.of(value.get().jsonNodeValue());
default:
return Optional.of(value.get().stringValue());
}
@@ -258,7 +260,7 @@ public Optional getDoubleAssignment(String subjectKey, String experiment
* @param subjectAttributes
* @return
*/
- public Optional getJSONAssignment(String subjectKey, String experimentKey,
+ public Optional getJSONStringAssignment(String subjectKey, String experimentKey,
SubjectAttributes subjectAttributes) {
return this.getStringAssignment(subjectKey, experimentKey, subjectAttributes);
}
@@ -271,8 +273,34 @@ public Optional getJSONAssignment(String subjectKey, String experimentKe
* @param experimentKey
* @return
*/
- public Optional getJSONAssignment(String subjectKey, String experimentKey) {
- return this.getJSONAssignment(subjectKey, experimentKey, new SubjectAttributes());
+ public Optional getJSONStringAssignment(String subjectKey, String experimentKey) {
+ return this.getJSONStringAssignment(subjectKey, experimentKey, new SubjectAttributes());
+ }
+
+ /**
+ * This function will return JSON assignment value
+ *
+ * @param subjectKey
+ * @param experimentKey
+ * @param subjectAttributes
+ * @return
+ */
+ public Optional getParsedJSONAssignment(String subjectKey, String experimentKey,
+ SubjectAttributes subjectAttributes) {
+ return (Optional) this.getTypedAssignment(subjectKey, experimentKey, EppoValueType.JSON_NODE,
+ subjectAttributes);
+ }
+
+ /**
+ * This function will return JSON assignment value without passing
+ * subjectAttributes
+ *
+ * @param subjectKey
+ * @param experimentKey
+ * @return
+ */
+ public Optional getParsedJSONAssignment(String subjectKey, String experimentKey) {
+ return this.getParsedJSONAssignment(subjectKey, experimentKey, new SubjectAttributes());
}
/**
diff --git a/src/test/java/com/eppo/sdk/EppoClientTest.java b/src/test/java/com/eppo/sdk/EppoClientTest.java
index 3243b55..0000ebf 100644
--- a/src/test/java/com/eppo/sdk/EppoClientTest.java
+++ b/src/test/java/com/eppo/sdk/EppoClientTest.java
@@ -11,7 +11,6 @@
import com.eppo.sdk.dto.*;
import com.eppo.sdk.helpers.Converter;
-import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -31,7 +30,6 @@
import lombok.Data;
-
@ExtendWith(WireMockExtension.class)
public class EppoClientTest {
@@ -120,15 +118,15 @@ public AssignmentValueType deserialize(JsonParser jsonParser, DeserializationCon
void init() {
setupMockRacServer();
EppoClientConfig config = EppoClientConfig.builder()
- .apiKey("mock-api-key")
- .baseURL("http://localhost:4001")
- .assignmentLogger(new IAssignmentLogger() {
- @Override
- public void logAssignment(AssignmentLogData logData) {
- // Auto-generated method stub
- }
- })
- .build();
+ .apiKey("mock-api-key")
+ .baseURL("http://localhost:4001")
+ .assignmentLogger(new IAssignmentLogger() {
+ @Override
+ public void logAssignment(AssignmentLogData logData) {
+ // Auto-generated method stub
+ }
+ })
+ .build();
EppoClient.init(config);
}
@@ -136,7 +134,8 @@ private void setupMockRacServer() {
this.mockServer = new WireMockServer(TEST_PORT);
this.mockServer.start();
String racResponseJson = getMockRandomizedAssignmentResponse();
- this.mockServer.stubFor(WireMock.get(WireMock.urlMatching(".*randomized_assignment.*")).willReturn(WireMock.okJson(racResponseJson)));
+ this.mockServer.stubFor(
+ WireMock.get(WireMock.urlMatching(".*randomized_assignment.*")).willReturn(WireMock.okJson(racResponseJson)));
}
@AfterEach
@@ -159,8 +158,14 @@ void testAssignments(AssignmentTestCase testCase) throws IOException {
assertEquals(expectedBooleanAssignments, actualBooleanAssignments);
break;
case JSON:
- List actualJSONAssignments = this.getJSONAssignments(testCase);
- assertEquals(testCase.expectedAssignments, actualJSONAssignments);
+ List actualJSONAssignments = this.getJSONAssignments(testCase);
+ for (JsonNode node : actualJSONAssignments) {
+ assertEquals(JsonNodeType.OBJECT, node.getNodeType());
+ }
+
+ assertEquals(testCase.expectedAssignments, actualJSONAssignments.stream()
+ .map(node -> node.toString())
+ .collect(Collectors.toList()));
break;
default:
List actualStringAssignments = this.getStringAssignments(testCase);
@@ -173,48 +178,49 @@ private List> getAssignments(AssignmentTestCase testCase, AssignmentValueType
EppoClient client = EppoClient.getInstance();
if (testCase.subjectsWithAttributes != null) {
return testCase.subjectsWithAttributes.stream()
+ .map(subject -> {
+ try {
+ switch (valueType) {
+ case NUMERIC:
+ return client.getDoubleAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
+ .orElse(null);
+ case BOOLEAN:
+ return client.getBooleanAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
+ .orElse(null);
+ case JSON:
+ return client
+ .getParsedJSONAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
+ .orElse(null);
+ default:
+ return client.getStringAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
+ .orElse(null);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }).collect(Collectors.toList());
+ }
+ return testCase.subjects.stream()
.map(subject -> {
try {
switch (valueType) {
case NUMERIC:
- return client.getDoubleAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
- .orElse(null);
+ return client.getDoubleAssignment(subject, testCase.experiment)
+ .orElse(null);
case BOOLEAN:
- return client.getBooleanAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
- .orElse(null);
+ return client.getBooleanAssignment(subject, testCase.experiment)
+ .orElse(null);
case JSON:
- return client.getJSONAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
- .orElse(null);
+ return client.getParsedJSONAssignment(subject, testCase.experiment)
+ .orElse(null);
default:
- return client.getStringAssignment(subject.subjectKey, testCase.experiment, subject.subjectAttributes)
- .orElse(null);
+ return client.getStringAssignment(subject, testCase.experiment)
+ .orElse(null);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
- }
- return testCase.subjects.stream()
- .map(subject -> {
- try {
- switch (valueType) {
- case NUMERIC:
- return client.getDoubleAssignment(subject, testCase.experiment)
- .orElse(null);
- case BOOLEAN:
- return client.getBooleanAssignment(subject, testCase.experiment)
- .orElse(null);
- case JSON:
- return client.getJSONAssignment(subject, testCase.experiment)
- .orElse(null);
- default:
- return client.getStringAssignment(subject, testCase.experiment)
- .orElse(null);
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }).collect(Collectors.toList());
}
private List getStringAssignments(AssignmentTestCase testCase) {
@@ -229,8 +235,8 @@ private List getBooleanAssignments(AssignmentTestCase testCase) {
return (List) this.getAssignments(testCase, AssignmentValueType.BOOLEAN);
}
- private List getJSONAssignments(AssignmentTestCase testCase) {
- return (List) this.getAssignments(testCase, AssignmentValueType.JSON);
+ private List getJSONAssignments(AssignmentTestCase testCase) {
+ return (List) this.getAssignments(testCase, AssignmentValueType.JSON);
}
private static Stream getAssignmentTestData() throws IOException {
@@ -248,7 +254,7 @@ private static Stream getAssignmentTestData() throws IOException {
private static String getMockRandomizedAssignmentResponse() {
File mockRacResponse = new File("src/test/resources/rac-experiments-v3.json");
try {
- return FileUtils.readFileToString(mockRacResponse, "UTF8");
+ return FileUtils.readFileToString(mockRacResponse, "UTF8");
} catch (Exception e) {
throw new RuntimeException("Error reading mock RAC data", e);
}