-
Notifications
You must be signed in to change notification settings - Fork 32
feature: add OptimizelyJSON #371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Pull Request Test Coverage Report for Build 1389
💛 - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getValue should not return anything, but it should modify the object passed in by reference.
Can you also make tests similar to the tests in go sdk ?
https://github.com/optimizely/go-sdk/blob/master/pkg/optimizelyjson/optimizely_json_test.go
Also please include the test to check if you don't destroy original object (it's also in my go tests)
core-api/src/main/java/com/optimizely/ab/optimizelyjson/OptimizelyJSON.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks fine, but there's a larger question around JSON serialization libraries that we need to address.
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't assume that Gson
is available. I see two options:
- We mimic the approach taken in DefaultConfigParser
- Take a stance on the serializer and include as a shadow dependency
Option 1 is the safer approach, since it has some precedence, but adds SDK complexity.
Option 2 is preferred but has a larger impact to the customer (my main concern is mobile).
cc @mikeng13
assertEquals((Double)md1.k3.kk2.kkk4[0], 5.7, 0.01); | ||
assertEquals(md1.k3.kk2.kkk4[2], "vvv4"); | ||
|
||
// verify previous getValue does not destroy the data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the purpose of this test is to call getValue twice with non empty json path on the same object. That will check if we don't modify the object by traversing and returning just a subset of the object. Both getValue calls need to have at least the same root of the json path (or the same json path)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've requested some cleanup on the tests to be more inline with the testing framework best practices. We're also missing a lot of unit test coverage on the parsers directly.
String toJson(Object src) throws ConfigParseException; | ||
<T> T fromJson(String json, Class<T> clazz) throws ConfigParseException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we create a new exception JsonParseException
for these?
@@ -52,4 +53,17 @@ public ProjectConfig parseProjectConfig(@Nonnull String json) throws ConfigParse | |||
throw new ConfigParseException("Unable to parse datafile: " + json, e); | |||
} | |||
} | |||
|
|||
public String toJson(Object src) { | |||
return new Gson().toJson(src); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realizing that we're not caching our Gson objects. I think this is worth benchmarking as this can be a performance bottleneck. Note that the JacksonConfigParser
stores an ObjectMapper
on the class implementation. This might have been ok when periodically parsing the Datafile, but if OptimizelyJSON is used heavily this could be an issue.
@Override | ||
public <T> T fromJson(String json, Class<T> clazz) throws ConfigParseException { | ||
if (Map.class.isAssignableFrom(clazz)) { | ||
org.json.JSONObject obj = new org.json.JSONObject(json); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're using org.json.JSONObject
and not org.json.simple
.
*/ | ||
package com.optimizely.ab.config.parser; | ||
|
||
public final class UnsupportedOperationException extends Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnsupportedOperationException
is also a built-in Java runtime exception that we shouldn't implement our own checked exception with the same name as this is confusing.
@Nullable | ||
public <T> T getValue(@Nullable String jsonKey, Class<T> clazz) throws UnsupportedOperationException { | ||
if (!(parser instanceof GsonConfigParser || parser instanceof JacksonConfigParser)) { | ||
throw new UnsupportedOperationException("A proper JSON parser is not available. Use Gson or Jackson parser for this operation."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per previous comment re: UnsupportedOperationException
consider throwing a runtime exception or renaming to something like a JsonParserException
.
|
||
import static org.junit.Assert.*; | ||
|
||
public class OptimizelyJSONExtendedTest extends OptimizelyJSONCoreTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of Core vs Extended you can use assumeThat to conditionally ignore a parameterized variant.
return new GsonConfigParser(); | ||
} | ||
|
||
// Tests for GSON only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess these classes are ok, but per the comments above, they should not be extending from OptimizelyJSONExtendedTest
.
*/ | ||
package com.optimizely.ab.optimizelyjson.types; | ||
|
||
public class MD1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear what these test classes are supposed to represent. It might be clearer if you subclass these under something like TestTypes.MD1
etc and add some doc strings.
|
||
import java.util.*; | ||
|
||
final class JsonHelpers { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a corresponding JsonHelpersTest
class for unit tests.
@@ -61,4 +63,23 @@ public ProjectConfigModule() { | |||
addDeserializer(Condition.class, new ConditionJacksonDeserializer(objectMapper)); | |||
} | |||
} | |||
|
|||
@Override | |||
public String toJson(Object src) throws ConfigParseException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're missing unit tests on these new implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Summary