Skip to content
Draft
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
77 changes: 40 additions & 37 deletions src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,39 +54,6 @@ public JsonLogic() {
addOperation(MissingExpression.SOME);
}

public JsonLogic addOperation(String name, Function<Object[], Object> function) {
return addOperation(new PreEvaluatedArgumentsExpression() {
@Override
public Object evaluate(List arguments, Object data, String jsonPath) {
return function.apply(arguments.toArray());
}

@Override
public String key() {
return name;
}
});
}

public JsonLogic addOperation(JsonLogicExpression expression) {
expressions.put(expression.key(), expression);
evaluator = null;

return this;
}

public Object apply(String json, Object data) throws JsonLogicException {
if (!parseCache.containsKey(json)) {
parseCache.put(json, JsonLogicParser.parse(json));
}

if (evaluator == null) {
evaluator = new JsonLogicEvaluator(expressions);
}

return evaluator.evaluate(parseCache.get(json), data, "$");
}

public static boolean truthy(Object value) {
if (value == null) {
return false;
Expand All @@ -102,8 +69,7 @@ public static boolean truthy(Object value) {

if (d.isNaN()) {
return false;
}
else if (d.isInfinite()) {
} else if (d.isInfinite()) {
return true;
}
}
Expand All @@ -113,8 +79,7 @@ else if (d.isInfinite()) {

if (f.isNaN()) {
return false;
}
else if (f.isInfinite()) {
} else if (f.isInfinite()) {
return true;
}
}
Expand All @@ -136,4 +101,42 @@ else if (f.isInfinite()) {

return true;
}

public JsonLogic addOperation(String name, Function<Object[], Object> function) {
return addOperation(new PreEvaluatedArgumentsExpression() {
@Override
public Object evaluate(List arguments, Object data, String jsonPath) {
return function.apply(arguments.toArray());
}

@Override
public String key() {
return name;
}
});
}

public JsonLogic addOperation(JsonLogicExpression expression) {
expressions.put(expression.key(), expression);
evaluator = null;

return this;
}

public Object apply(String json, Object data) throws JsonLogicException {
if (!parseCache.containsKey(json)) {
parseCache.put(json, JsonLogicParser.parse(json));
}

if (evaluator == null) {
evaluator = new JsonLogicEvaluator(expressions);
}

try {
return evaluator.evaluate(parseCache.get(json), data, "");
} catch (JsonLogicException e) {
e.prependPartialJsonPath("$");
throw e;
}
}
}
29 changes: 24 additions & 5 deletions src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,47 @@

public class JsonLogicException extends Exception {

private String jsonPath;
private final StringBuilder jsonPath = new StringBuilder();

private JsonLogicException() {
// The default constructor should not be called for exceptions. A reason must be provided.
}

public JsonLogicException(String msg) {
super(msg);
}

public JsonLogicException(String msg, String jsonPath) {
super(msg);
this.jsonPath = jsonPath;
prependPartialJsonPath(jsonPath);
}

public JsonLogicException(Throwable cause) {
super(cause);
}

public JsonLogicException(Throwable cause, String jsonPath) {
super(cause);
this.jsonPath = jsonPath;
prependPartialJsonPath(jsonPath);
}

public JsonLogicException(String msg, Throwable cause) {
super(msg, cause);
}

public JsonLogicException(String msg, Throwable cause, String jsonPath) {
super(msg, cause);
this.jsonPath = jsonPath;
prependPartialJsonPath(jsonPath);
}

public String getJsonPath() {
return jsonPath;
return jsonPath.toString();
}

public void prependPartialJsonPath(String partialPath) {
if (partialPath == null) {
return;
}
jsonPath.insert(0, partialPath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ public JsonLogicParseException(Throwable cause, String jsonPath) {
public JsonLogicParseException(String msg, Throwable cause, String jsonPath) {
super(msg, cause, jsonPath);
}

public JsonLogicParseException(String msg) {
super(msg);
}
}
39 changes: 25 additions & 14 deletions src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ private JsonLogicParser() {
public static JsonLogicNode parse(String json) throws JsonLogicParseException {
try {
return parse(PARSER.parse(json));
}
catch (JsonSyntaxException e) {
} catch (JsonLogicParseException e) {
e.prependPartialJsonPath("$");
throw e;
} catch (JsonSyntaxException e) {
throw new JsonLogicParseException(e, "$");
}
}

private static JsonLogicNode parse(JsonElement root) throws JsonLogicParseException {
return parse(root, "$");
}
private static JsonLogicNode parse(JsonElement root, String jsonPath) throws JsonLogicParseException {
// Handle null
if (root.isJsonNull()) {
return JsonLogicNull.NULL;
Expand All @@ -45,8 +44,7 @@ private static JsonLogicNode parse(JsonElement root, String jsonPath) throws Jso

if (primitive.isBoolean() && primitive.getAsBoolean()) {
return JsonLogicBoolean.TRUE;
}
else {
} else {
return JsonLogicBoolean.FALSE;
}
}
Expand All @@ -56,9 +54,16 @@ private static JsonLogicNode parse(JsonElement root, String jsonPath) throws Jso
JsonArray array = root.getAsJsonArray();
List<JsonLogicNode> elements = new ArrayList<>(array.size());

int index = 0;
for (JsonElement element : array) {
elements.add(parse(element, String.format("%s[%d]", jsonPath, index++)));
for (int index = 0; index < array.size(); index++) {
JsonElement element = array.get(index);
JsonLogicNode arrayNode;
try {
arrayNode = parse(element);
} catch (JsonLogicParseException e) {
e.prependPartialJsonPath("[" + (index) + "]");
throw e;
}
elements.add(arrayNode);
}

return new JsonLogicArray(elements);
Expand All @@ -68,18 +73,24 @@ private static JsonLogicNode parse(JsonElement root, String jsonPath) throws Jso
JsonObject object = root.getAsJsonObject();

if (object.keySet().size() != 1) {
throw new JsonLogicParseException("objects must have exactly 1 key defined, found " + object.keySet().size(), jsonPath);
throw new JsonLogicParseException("objects must have exactly 1 key defined, found " + object.keySet().size());
}

String key = object.keySet().stream().findAny().get();
JsonLogicNode argumentNode = parse(object.get(key), String.format("%s.%s", jsonPath, key));
JsonLogicNode argumentNode;
JsonLogicArray arguments;

try {
argumentNode = parse(object.get(key));
} catch (JsonLogicParseException e) {
e.prependPartialJsonPath("." + key);
throw e;
}

// Always coerce single-argument operations into a JsonLogicArray with a single element.
if (argumentNode instanceof JsonLogicArray) {
arguments = (JsonLogicArray) argumentNode;
}
else {
} else {
arguments = new JsonLogicArray(Collections.singletonList(argumentNode));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@
import io.github.jamsesso.jsonlogic.JsonLogicException;

public class JsonLogicEvaluationException extends JsonLogicException {
public JsonLogicEvaluationException(String msg) {
super(msg);
}

public JsonLogicEvaluationException(String msg, String jsonPath) {
super(msg, jsonPath);
}

public JsonLogicEvaluationException(Throwable cause) {
super(cause);
}

public JsonLogicEvaluationException(Throwable cause, String jsonPath) {
super(cause, jsonPath);
}

public JsonLogicEvaluationException(String msg, Throwable cause) {
super(msg, cause);
}

public JsonLogicEvaluationException(String msg, Throwable cause, String jsonPath) {
super(msg, cause, jsonPath);
}
Expand Down
Loading