blob: bbcd69bfd1c39e97f72fe5965e0976e855c43db0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.camel.jsonpath;
import java.util.Collection;
import java.util.List;
import com.jayway.jsonpath.Option;
import org.apache.camel.AfterPropertiesConfigured;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ExpressionEvaluationException;
import org.apache.camel.ExpressionIllegalSyntaxException;
import org.apache.camel.jsonpath.easypredicate.EasyPredicateParser;
import org.apache.camel.support.ExpressionAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JsonPathExpression extends ExpressionAdapter implements AfterPropertiesConfigured {
private static final Logger LOG = LoggerFactory.getLogger(JsonPathExpression.class);
private final String expression;
private JsonPathEngine engine;
private boolean predicate;
private Class<?> resultType;
private boolean suppressExceptions;
private boolean allowSimple = true;
private boolean allowEasyPredicate = true;
private boolean writeAsString;
private String headerName;
private Option[] options;
public JsonPathExpression(String expression) {
this.expression = expression;
}
public boolean isPredicate() {
return predicate;
}
/**
* Whether to be evaluated as a predicate
*/
public void setPredicate(boolean predicate) {
this.predicate = predicate;
}
public Class<?> getResultType() {
return resultType;
}
/**
* To configure the result type to use
*/
public void setResultType(Class<?> resultType) {
this.resultType = resultType;
}
public boolean isSuppressExceptions() {
return suppressExceptions;
}
/**
* Whether to suppress exceptions such as PathNotFoundException
*/
public void setSuppressExceptions(boolean suppressExceptions) {
this.suppressExceptions = suppressExceptions;
}
public boolean isAllowSimple() {
return allowSimple;
}
/**
* Whether to allow in inlined simple exceptions in the json path expression
*/
public void setAllowSimple(boolean allowSimple) {
this.allowSimple = allowSimple;
}
public boolean isAllowEasyPredicate() {
return allowEasyPredicate;
}
/**
* Whether to allow using the easy predicate parser to pre-parse predicates.
* See {@link EasyPredicateParser} for more details.
*/
public void setAllowEasyPredicate(boolean allowEasyPredicate) {
this.allowEasyPredicate = allowEasyPredicate;
}
public boolean isWriteAsString() {
return writeAsString;
}
/**
* Whether to write the output of each row/element as a JSon String value instead of a Map/POJO value.
*/
public void setWriteAsString(boolean writeAsString) {
this.writeAsString = writeAsString;
}
public String getHeaderName() {
return headerName;
}
/**
* Name of header to use as input, instead of the message body
*/
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
public Option[] getOptions() {
return options;
}
/**
* To configure the json path options to use
*/
public void setOptions(Option[] options) {
this.options = options;
}
@Override
public Object evaluate(Exchange exchange) {
try {
Object result = evaluateJsonPath(exchange, engine);
if (resultType != null) {
// in some cases we get a single element that is wrapped in a List, so unwrap that
// if we for example want to grab the single entity and convert that to a int/boolean/String etc
boolean resultIsCollection = Collection.class.isAssignableFrom(resultType);
boolean singleElement = result instanceof List && ((List) result).size() == 1;
if (singleElement && !resultIsCollection) {
result = ((List) result).get(0);
LOG.trace("Unwrapping result: {} from single element List before converting to: {}", result, resultType);
}
return exchange.getContext().getTypeConverter().convertTo(resultType, exchange, result);
} else {
return result;
}
} catch (Exception e) {
throw new ExpressionEvaluationException(this, exchange, e);
}
}
@Override
public void afterPropertiesConfigured(CamelContext camelContext) {
init();
}
public void init() {
String exp = expression;
if (predicate && isAllowEasyPredicate()) {
EasyPredicateParser parser = new EasyPredicateParser();
exp = parser.parse(expression);
if (!exp.equals(expression)) {
LOG.debug("EasyPredicateParser parsed {} -> {}", expression, exp);
}
}
LOG.debug("Initializing {} using: {}", predicate ? "predicate" : "expression", exp);
try {
engine = new JsonPathEngine(exp, writeAsString, suppressExceptions, allowSimple, headerName, options);
} catch (Exception e) {
throw new ExpressionIllegalSyntaxException(exp, e);
}
}
@Override
public String toString() {
return "jsonpath[" + expression + "]";
}
private Object evaluateJsonPath(Exchange exchange, JsonPathEngine engine) throws Exception {
return engine.read(exchange);
}
}