- 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
Changes from 15 commits
032c270 99014d2 9de2535 641d215 69144a0 f319fdc 096bcb9 5be5f3f 01970f5 2401784 afdb8be 2952834 24ed0d6 5d45085 2af6f14 b5db429 b6fc66c ef7963b 880111b 14ace05 f0df4e2 ceddf49 37efc58 8cd3b55 c92459f e5d792a File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /** | ||
| * | ||
| * Copyright 2016-2017, 2019, Optimizely and contributors | ||
| * Copyright 2016-2017, 2019-2020, Optimizely and contributors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| | @@ -18,6 +18,7 @@ | |
| | ||
| import com.google.gson.Gson; | ||
| import com.google.gson.GsonBuilder; | ||
| import com.google.gson.JsonSyntaxException; | ||
| import com.optimizely.ab.config.*; | ||
| import com.optimizely.ab.config.audience.Audience; | ||
| import com.optimizely.ab.config.audience.TypedAudience; | ||
| | @@ -27,7 +28,7 @@ | |
| /** | ||
| * {@link Gson}-based config parser implementation. | ||
| */ | ||
| final class GsonConfigParser implements ConfigParser { | ||
| final public class GsonConfigParser implements ConfigParser { | ||
| | ||
| @Override | ||
| public ProjectConfig parseProjectConfig(@Nonnull String json) throws ConfigParseException { | ||
| | @@ -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); | ||
| ||
| } | ||
| | ||
| public <T> T fromJson(String json, Class<T> clazz) throws ConfigParseException { | ||
| try { | ||
| return new Gson().fromJson(json, clazz); | ||
| } catch (Exception e) { | ||
| throw new ConfigParseException("Unable to parse JSON string: " + e.toString()); | ||
| } | ||
| } | ||
| | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /** | ||
| * | ||
| * Copyright 2016-2018, Optimizely and contributors | ||
| * Copyright 2016-2018, 2020, Optimizely and contributors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| | @@ -16,6 +16,7 @@ | |
| */ | ||
| package com.optimizely.ab.config.parser; | ||
| | ||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import com.fasterxml.jackson.databind.module.SimpleModule; | ||
| import com.optimizely.ab.config.DatafileProjectConfig; | ||
| | @@ -25,11 +26,12 @@ | |
| import com.optimizely.ab.config.audience.TypedAudience; | ||
| | ||
| import javax.annotation.Nonnull; | ||
| import java.io.IOException; | ||
| | ||
| /** | ||
| * {@code Jackson}-based config parser implementation. | ||
| */ | ||
| final class JacksonConfigParser implements ConfigParser { | ||
| final public class JacksonConfigParser implements ConfigParser { | ||
| private ObjectMapper objectMapper; | ||
| | ||
| public JacksonConfigParser() { | ||
| | @@ -61,4 +63,23 @@ public ProjectConfigModule() { | |
| addDeserializer(Condition.class, new ConditionJacksonDeserializer(objectMapper)); | ||
| } | ||
| } | ||
| | ||
| @Override | ||
| public String toJson(Object src) throws ConfigParseException { | ||
| ||
| try { | ||
| return objectMapper.writeValueAsString(src); | ||
| } catch (JsonProcessingException e) { | ||
| throw new ConfigParseException("Serialization failed: " + e.toString()); | ||
| } | ||
| } | ||
| | ||
| @Override | ||
| public <T> T fromJson(String json, Class<T> clazz) throws ConfigParseException { | ||
| try { | ||
| return objectMapper.readValue(json, clazz); | ||
| } catch (IOException e) { | ||
| throw new ConfigParseException("Unable to parse JSON string: " + e.toString()); | ||
| } | ||
| } | ||
| | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /** | ||
| * | ||
| * Copyright 2020, Optimizely and contributors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package com.optimizely.ab.config.parser; | ||
| | ||
| import org.json.JSONArray; | ||
| import org.json.JSONObject; | ||
| | ||
| import java.util.*; | ||
| | ||
| final class JsonHelpers { | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should have a corresponding | ||
| | ||
| static Object convertToJsonObject(Object obj) { | ||
| if (obj instanceof Map) { | ||
| Map<Object, Object> map = (Map)obj; | ||
| JSONObject jObj = new JSONObject(); | ||
| for (Map.Entry entry : map.entrySet()) { | ||
| jObj.put(entry.getKey().toString(), convertToJsonObject(entry.getValue())); | ||
| } | ||
| return jObj; | ||
| } else if (obj instanceof List) { | ||
| List list = (List)obj; | ||
| JSONArray jArray = new JSONArray(); | ||
| for (Object value : list) { | ||
| jArray.put(convertToJsonObject(value)); | ||
| } | ||
| return jArray; | ||
| } else { | ||
| return obj; | ||
| } | ||
| } | ||
| | ||
| static Map<String, Object> jsonObjectToMap(JSONObject jObj) { | ||
| Map<String, Object> map = new HashMap<>(); | ||
| | ||
| Iterator<String> keys = jObj.keys(); | ||
| while(keys.hasNext()) { | ||
| String key = keys.next(); | ||
| Object value = jObj.get(key); | ||
| | ||
| if (value instanceof JSONArray) { | ||
| value = jsonArrayToList((JSONArray)value); | ||
| } else if (value instanceof JSONObject) { | ||
| value = jsonObjectToMap((JSONObject)value); | ||
| } | ||
| | ||
| map.put(key, value); | ||
| } | ||
| | ||
| return map; | ||
| } | ||
| | ||
| static List<Object> jsonArrayToList(JSONArray array) { | ||
| List<Object> list = new ArrayList<>(); | ||
| for(Object value : array) { | ||
| if (value instanceof JSONArray) { | ||
| value = jsonArrayToList((JSONArray)value); | ||
| } else if (value instanceof JSONObject) { | ||
| value = jsonObjectToMap((JSONObject)value); | ||
| } | ||
| | ||
| list.add(value); | ||
| } | ||
| | ||
| return list; | ||
| } | ||
| | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /** | ||
| * | ||
| * Copyright 2016-2019, Optimizely and contributors | ||
| * Copyright 2016-2019, 2020, Optimizely and contributors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| | @@ -26,6 +26,7 @@ | |
| import com.optimizely.ab.internal.ConditionUtils; | ||
| import org.json.simple.JSONArray; | ||
| import org.json.simple.JSONObject; | ||
| import org.json.simple.JSONValue; | ||
| import org.json.simple.parser.JSONParser; | ||
| import org.json.simple.parser.ParseException; | ||
| | ||
| | @@ -41,7 +42,7 @@ | |
| /** | ||
| * {@code json-simple}-based config parser implementation. | ||
| */ | ||
| final class JsonSimpleConfigParser implements ConfigParser { | ||
| final public class JsonSimpleConfigParser implements ConfigParser { | ||
| | ||
| @Override | ||
| public ProjectConfig parseProjectConfig(@Nonnull String json) throws ConfigParseException { | ||
| | @@ -371,5 +372,22 @@ private List<Rollout> parseRollouts(JSONArray rolloutsJson) { | |
| | ||
| return rollouts; | ||
| } | ||
| | ||
| @Override | ||
| public String toJson(Object src) { | ||
| return JSONValue.toJSONString(src); | ||
| } | ||
| | ||
| @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 commentThe reason will be displayed to describe this comment to others. Learn more. You're using | ||
| return (T)JsonHelpers.jsonObjectToMap(obj); | ||
| } | ||
| | ||
| // org.json.simple does not support parsing to user objects | ||
| throw new ConfigParseException("Parsing fails with a unsupported type"); | ||
| } | ||
| | ||
| } | ||
| | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| * | ||
| * Copyright 2020, Optimizely and contributors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package com.optimizely.ab.config.parser; | ||
| | ||
| public final class UnsupportedOperationException extends Exception { | ||
| ||
| public UnsupportedOperationException(String message) { | ||
| super(message); | ||
| } | ||
| | ||
| public UnsupportedOperationException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
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
JsonParseExceptionfor these?