Search in sources :

Example 1 with Parameter

use of com.jayway.jsonpath.internal.function.Parameter in project JsonPath by jayway.

the class Append method invoke.

@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
    JsonProvider jsonProvider = ctx.configuration().jsonProvider();
    if (parameters != null && parameters.size() > 0) {
        for (Parameter param : parameters) {
            if (jsonProvider.isArray(model)) {
                int len = jsonProvider.length(model);
                jsonProvider.setArrayIndex(model, len, param.getCachedValue());
            }
        }
    }
    return model;
}
Also used : Parameter(com.jayway.jsonpath.internal.function.Parameter) JsonProvider(com.jayway.jsonpath.spi.json.JsonProvider)

Example 2 with Parameter

use of com.jayway.jsonpath.internal.function.Parameter in project JsonPath by jayway.

the class FunctionPathToken method evaluateParameters.

private void evaluateParameters(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
    if (null != functionParams) {
        for (Parameter param : functionParams) {
            if (!param.hasEvaluated()) {
                switch(param.getType()) {
                    case PATH:
                        param.setCachedValue(param.getPath().evaluate(ctx.rootDocument(), ctx.rootDocument(), ctx.configuration()).getValue());
                        param.setEvaluated(true);
                        break;
                    case JSON:
                        param.setCachedValue(ctx.configuration().jsonProvider().parse(param.getJson()));
                        param.setEvaluated(true);
                        break;
                }
            }
        }
    }
}
Also used : Parameter(com.jayway.jsonpath.internal.function.Parameter)

Example 3 with Parameter

use of com.jayway.jsonpath.internal.function.Parameter in project JsonPath by jayway.

the class PathCompiler method parseFunctionParameters.

/**
     * Parse the parameters of a function call, either the caller has supplied JSON data, or the caller has supplied
     * another path expression which must be evaluated and in turn invoked against the root document.  In this tokenizer
     * we're only concerned with parsing the path thus the output of this function is a list of parameters with the Path
     * set if the parameter is an expression.  If the parameter is a JSON document then the value of the cachedValue is
     * set on the object.
     *
     * Sequence for parsing out the parameters:
     *
     * This code has its own tokenizer - it does some rudimentary level of lexing in that it can distinguish between JSON block parameters
     * and sub-JSON blocks - it effectively regex's out the parameters into string blocks that can then be passed along to the appropriate parser.
     * Since sub-jsonpath expressions can themselves contain other function calls this routine needs to be sensitive to token counting to
     * determine the boundaries.  Since the Path parser isn't aware of JSON processing this uber routine is needed.
     *
     * Parameters are separated by COMMAs ','
     *
     * <pre>
     * doc = {"numbers": [1,2,3,4,5,6,7,8,9,10]}
     *
     * $.sum({10}, $.numbers.avg())
     * </pre>
     *
     * The above is a valid function call, we're first summing 10 + avg of 1...10 (5.5) so the total should be 15.5
     *
     * @return
     *      An ordered list of parameters that are to processed via the function.  Typically functions either process
     *      an array of values and/or can consume parameters in addition to the values provided from the consumption of
     *      an array.
     */
private List<Parameter> parseFunctionParameters(String funcName) {
    PathToken currentToken;
    ParamType type = null;
    // Parenthesis starts at 1 since we're marking the start of a function call, the close paren will denote the
    // last parameter boundary
    Integer groupParen = 1, groupBracket = 0, groupBrace = 0, groupQuote = 0;
    Boolean endOfStream = false;
    char priorChar = 0;
    List<Parameter> parameters = new ArrayList<Parameter>();
    StringBuffer parameter = new StringBuffer();
    while (path.inBounds() && !endOfStream) {
        char c = path.currentChar();
        path.incrementPosition(1);
        // we're at the start of the stream, and don't know what type of parameter we have
        if (type == null) {
            if (isWhitespace(c)) {
                continue;
            }
            if (c == OPEN_BRACE || isDigit(c) || DOUBLE_QUOTE == c) {
                type = ParamType.JSON;
            } else if (isPathContext(c)) {
                // read until we reach a terminating comma and we've reset grouping to zero
                type = ParamType.PATH;
            }
        }
        switch(c) {
            case DOUBLE_QUOTE:
                if (priorChar != '\\' && groupQuote > 0) {
                    if (groupQuote == 0) {
                        throw new InvalidPathException("Unexpected quote '\"' at character position: " + path.position());
                    }
                    groupQuote--;
                } else {
                    groupQuote++;
                }
                break;
            case OPEN_PARENTHESIS:
                groupParen++;
                break;
            case OPEN_BRACE:
                groupBrace++;
                break;
            case OPEN_SQUARE_BRACKET:
                groupBracket++;
                break;
            case CLOSE_BRACE:
                if (0 == groupBrace) {
                    throw new InvalidPathException("Unexpected close brace '}' at character position: " + path.position());
                }
                groupBrace--;
                break;
            case CLOSE_SQUARE_BRACKET:
                if (0 == groupBracket) {
                    throw new InvalidPathException("Unexpected close bracket ']' at character position: " + path.position());
                }
                groupBracket--;
                break;
            // we've encountered a COMMA do the same
            case CLOSE_PARENTHESIS:
                groupParen--;
                if (0 != groupParen) {
                    parameter.append(c);
                }
            case COMMA:
                // to the parser
                if ((0 == groupQuote && 0 == groupBrace && 0 == groupBracket && ((0 == groupParen && CLOSE_PARENTHESIS == c) || 1 == groupParen))) {
                    endOfStream = (0 == groupParen);
                    if (null != type) {
                        Parameter param = null;
                        switch(type) {
                            case JSON:
                                // parse the json and set the value
                                param = new Parameter(parameter.toString());
                                break;
                            case PATH:
                                LinkedList<Predicate> predicates = new LinkedList<Predicate>();
                                PathCompiler compiler = new PathCompiler(parameter.toString(), predicates);
                                param = new Parameter(compiler.compile());
                                break;
                        }
                        if (null != param) {
                            parameters.add(param);
                        }
                        parameter.delete(0, parameter.length());
                        type = null;
                    }
                }
                break;
        }
        if (type != null && !(c == COMMA && 0 == groupBrace && 0 == groupBracket && 1 == groupParen)) {
            parameter.append(c);
        }
        priorChar = c;
    }
    if (0 != groupBrace || 0 != groupParen || 0 != groupBracket) {
        throw new InvalidPathException("Arguments to function: '" + funcName + "' are not closed properly.");
    }
    return parameters;
}
Also used : ArrayList(java.util.ArrayList) ParamType(com.jayway.jsonpath.internal.function.ParamType) InvalidPathException(com.jayway.jsonpath.InvalidPathException) LinkedList(java.util.LinkedList) Predicate(com.jayway.jsonpath.Predicate) Parameter(com.jayway.jsonpath.internal.function.Parameter)

Example 4 with Parameter

use of com.jayway.jsonpath.internal.function.Parameter in project JsonPath by jayway.

the class AbstractAggregation method invoke.

@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
    int count = 0;
    if (ctx.configuration().jsonProvider().isArray(model)) {
        Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);
        for (Object obj : objects) {
            if (obj instanceof Number) {
                Number value = (Number) obj;
                count++;
                next(value);
            }
        }
    }
    if (parameters != null) {
        for (Parameter param : parameters) {
            if (param.getCachedValue() instanceof Number) {
                Number value = (Number) param.getCachedValue();
                count++;
                next(value);
            }
        }
    }
    if (count != 0) {
        return getValue();
    }
    throw new JsonPathException("Aggregation function attempted to calculate value using empty array");
}
Also used : Parameter(com.jayway.jsonpath.internal.function.Parameter) JsonPathException(com.jayway.jsonpath.JsonPathException)

Aggregations

Parameter (com.jayway.jsonpath.internal.function.Parameter)4 InvalidPathException (com.jayway.jsonpath.InvalidPathException)1 JsonPathException (com.jayway.jsonpath.JsonPathException)1 Predicate (com.jayway.jsonpath.Predicate)1 ParamType (com.jayway.jsonpath.internal.function.ParamType)1 JsonProvider (com.jayway.jsonpath.spi.json.JsonProvider)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1