Skip to content
Open
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
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,4 +514,27 @@ CacheProvider.setCache(new Cache() {
});
```

### Path Function Provider SPI

This SPI allows adding, overriding, and removing the path functions available in the JsonPath path.
Therefore, change the `PathFunctionProvider` of the `Configuration`.

```java
String json = "...";

Configuration conf = Configuration.defaultConfiguration().pathFunctionProvider(new DefaultPathFunctionProvider() {
@Override
public PathFunction newFunction(String name) throws InvalidPathException {
if (name.equals("toUpperCase")) {
return (currentPath, parent, model, ctx, parameters) -> ((String) model).toUpperCase();
}

// Fall back to default functions
return super.newFunction(name);
}
});

JsonPath.using(conf).parse(json).read("$.store.book[0].author.toUpperCase()").toString(); // NIGEL REES
```

[![Analytics](https://ga-beacon.appspot.com/UA-54945131-1/jsonpath/index)](https://github.com/igrigorik/ga-beacon)
78 changes: 70 additions & 8 deletions json-path/src/main/java/com/jayway/jsonpath/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
package com.jayway.jsonpath;

import com.jayway.jsonpath.internal.DefaultsImpl;
import com.jayway.jsonpath.spi.pathFunction.DefaultPathFunctionProvider;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
import com.jayway.jsonpath.spi.pathFunction.PathFunctionProvider;

import java.util.*;

Expand Down Expand Up @@ -50,16 +53,19 @@ private static Defaults getEffectiveDefaults(){
private final MappingProvider mappingProvider;
private final Set<Option> options;
private final Collection<EvaluationListener> evaluationListeners;
private final PathFunctionProvider pathFunctionProvider;

private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider, EnumSet<Option> options, Collection<EvaluationListener> evaluationListeners) {
private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider, EnumSet<Option> options, Collection<EvaluationListener> evaluationListeners, PathFunctionProvider pathFunctionProvider) {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(mappingProvider, "mappingProvider can not be null");
notNull(options, "setOptions can not be null");
notNull(evaluationListeners, "evaluationListeners can not be null");
notNull(pathFunctionProvider, "pathFunctionProvider can not be null");
this.jsonProvider = jsonProvider;
this.mappingProvider = mappingProvider;
this.options = Collections.unmodifiableSet(options);
this.evaluationListeners = Collections.unmodifiableCollection(evaluationListeners);
this.pathFunctionProvider = pathFunctionProvider;
}

/**
Expand All @@ -68,7 +74,13 @@ private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider
* @return a new configuration
*/
public Configuration addEvaluationListeners(EvaluationListener... evaluationListener){
return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListener).build();
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(mappingProvider)
.options(options)
.evaluationListener(evaluationListener)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand All @@ -77,7 +89,13 @@ public Configuration addEvaluationListeners(EvaluationListener... evaluationList
* @return a new configuration
*/
public Configuration setEvaluationListeners(EvaluationListener... evaluationListener){
return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListener).build();
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(mappingProvider)
.options(options)
.evaluationListener(evaluationListener)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand All @@ -94,7 +112,13 @@ public Collection<EvaluationListener> getEvaluationListeners(){
* @return a new configuration
*/
public Configuration jsonProvider(JsonProvider newJsonProvider) {
return Configuration.builder().jsonProvider(newJsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListeners).build();
return Configuration.builder()
.jsonProvider(newJsonProvider)
.mappingProvider(mappingProvider)
.options(options)
.evaluationListener(evaluationListeners)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand All @@ -111,7 +135,13 @@ public JsonProvider jsonProvider() {
* @return a new configuration
*/
public Configuration mappingProvider(MappingProvider newMappingProvider) {
return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(newMappingProvider).options(options).evaluationListener(evaluationListeners).build();
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(newMappingProvider)
.options(options)
.evaluationListener(evaluationListeners)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand All @@ -122,6 +152,20 @@ public MappingProvider mappingProvider() {
return mappingProvider;
}

public Configuration pathFunctionProvider(PathFunctionProvider newPathFunctionProvider) {
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(mappingProvider)
.options(options)
.evaluationListener(evaluationListeners)
.pathFunctionProvider(newPathFunctionProvider)
.build();
}

public PathFunctionProvider pathFunctionProvider() {
return this.pathFunctionProvider;
}

/**
* Creates a new configuration by adding the new options to the options used in this configuration.
* @param options options to add
Expand All @@ -131,7 +175,13 @@ public Configuration addOptions(Option... options) {
EnumSet<Option> opts = EnumSet.noneOf(Option.class);
opts.addAll(this.options);
opts.addAll(asList(options));
return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(opts).evaluationListener(evaluationListeners).build();
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(mappingProvider)
.options(opts)
.evaluationListener(evaluationListeners)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand All @@ -140,7 +190,13 @@ public Configuration addOptions(Option... options) {
* @return the new configuration instance
*/
public Configuration setOptions(Option... options) {
return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListeners).build();
return Configuration.builder()
.jsonProvider(jsonProvider)
.mappingProvider(mappingProvider)
.options(options)
.evaluationListener(evaluationListeners)
.pathFunctionProvider(pathFunctionProvider)
.build();
}

/**
Expand Down Expand Up @@ -186,6 +242,7 @@ public static class ConfigurationBuilder {
private MappingProvider mappingProvider;
private EnumSet<Option> options = EnumSet.noneOf(Option.class);
private Collection<EvaluationListener> evaluationListener = new ArrayList<EvaluationListener>();
private PathFunctionProvider pathFunctionProvider = new DefaultPathFunctionProvider();

public ConfigurationBuilder jsonProvider(JsonProvider provider) {
this.jsonProvider = provider;
Expand Down Expand Up @@ -219,6 +276,11 @@ public ConfigurationBuilder evaluationListener(Collection<EvaluationListener> li
return this;
}

public ConfigurationBuilder pathFunctionProvider(PathFunctionProvider pathFunctionProvider) {
this.pathFunctionProvider = pathFunctionProvider;
return this;
}

public Configuration build() {
if (jsonProvider == null || mappingProvider == null) {
final Defaults defaults = getEffectiveDefaults();
Expand All @@ -229,7 +291,7 @@ public Configuration build() {
mappingProvider = defaults.mappingProvider();
}
}
return new Configuration(jsonProvider, mappingProvider, options, evaluationListener);
return new Configuration(jsonProvider, mappingProvider, options, evaluationListener, pathFunctionProvider);
}
}

Expand Down
2 changes: 1 addition & 1 deletion json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.jayway.jsonpath.internal.*;
import com.jayway.jsonpath.internal.path.PathCompiler;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.pathFunction.PathFunctionProvider;

import java.io.File;
import java.io.FileInputStream;
Expand Down Expand Up @@ -515,7 +516,6 @@ public static JsonPath compile(String jsonPath, Predicate... filters) {
return new JsonPath(jsonPath, filters);
}


// --------------------------------------------------------
//
// Static utility functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;
import com.jayway.jsonpath.spi.json.JsonProvider;

import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;

import java.util.ArrayList;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;
import com.jayway.jsonpath.internal.path.CompiledPath;
import com.jayway.jsonpath.internal.path.PathToken;
import com.jayway.jsonpath.internal.path.RootPathToken;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.pathFunction.PathFunctionProvider;

import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -98,6 +99,7 @@ public void addResult(String path, PathRef operation, Object model) {
}
}

public PathFunctionProvider functionProvider() { return configuration.pathFunctionProvider(); }

public JsonProvider jsonProvider() {
return configuration.jsonProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.internal.function.PathFunctionFactory;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;
import com.jayway.jsonpath.internal.function.latebinding.JsonLateBindingValue;
import com.jayway.jsonpath.internal.function.latebinding.PathLateBindingValue;
import com.jayway.jsonpath.spi.pathFunction.PathFunctionProvider;

import java.util.List;
import java.util.Map;

/**
* Token representing a Function call to one of the functions produced via the FunctionFactory
* Token representing a Function call to one of the functions produced via the FunctionProvider
*
* @see PathFunctionFactory
* @see PathFunctionProvider
*
* Created by mattg on 6/27/15.
*/
Expand All @@ -22,6 +23,7 @@ public class FunctionPathToken extends PathToken {
private final String functionName;
private final String pathFragment;
private List<Parameter> functionParams;
private Map<String, Class<? extends PathFunction>> customFunctions;

public FunctionPathToken(String pathFragment, List<Parameter> parameters) {
this.pathFragment = pathFragment + ((parameters != null && parameters.size() > 0) ? "(...)" : "()");
Expand All @@ -36,7 +38,7 @@ public FunctionPathToken(String pathFragment, List<Parameter> parameters) {

@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
PathFunction pathFunction = PathFunctionFactory.newFunction(functionName);
PathFunction pathFunction = ctx.functionProvider().newFunction(functionName);
evaluateParameters(currentPath, parent, model, ctx);
Object result = pathFunction.invoke(currentPath, parent, model, ctx, functionParams);
ctx.addResult(currentPath + "." + functionName, parent, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
import com.jayway.jsonpath.internal.filter.FilterCompiler;
import com.jayway.jsonpath.internal.function.ParamType;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.spi.pathFunction.PathFunctionProvider;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.*;

import static java.lang.Character.isDigit;
import static java.util.Arrays.asList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.pathFunction.PathFunction;
import com.jayway.jsonpath.spi.json.JsonProvider;

import java.util.List;
Expand Down
Loading