Browse Source

Rewrite intenals.

pull/41/head
Kalle Stenflo 11 years ago
parent
commit
608c1a77be
  1. 3
      json-path-assert/src/main/java/com/jayway/jsonassert/JsonAssert.java
  2. 20
      json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java
  3. 24
      json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java
  4. 120
      json-path-web-test/pom.xml
  5. 131
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Bench.java
  6. 22
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Result.java
  7. 58
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/boot/Main.java
  8. 96
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java
  9. 34
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/StaticResource.java
  10. 5785
      json-path-web-test/src/main/resources/css/bootstrap.css
  11. 1
      json-path-web-test/src/main/resources/css/bootstrap.css.map
  12. BIN
      json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.eot
  13. 229
      json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.svg
  14. BIN
      json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.ttf
  15. BIN
      json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.woff
  16. 1951
      json-path-web-test/src/main/resources/js/bootstrap.js
  17. 87
      json-path-web-test/src/main/resources/js/jsonpath-0.8.0.js
  18. 926
      json-path-web-test/src/main/resources/json/20k.json
  19. 50469
      json-path-web-test/src/main/resources/json/citm_catalog.json
  20. 1
      json-path-web-test/src/main/resources/json/goessner.json
  21. 298
      json-path-web-test/src/main/resources/json/twitter.json
  22. 100
      json-path-web-test/src/main/resources/json/webxml.json
  23. 2
      json-path-web-test/src/main/resources/simplelogger.properties
  24. 118
      json-path-web-test/src/main/resources/templates/index.mustache
  25. 10
      json-path/src/main/java/com/jayway/jsonpath/Configuration.java
  26. 143
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  27. 618
      json-path/src/main/java/com/jayway/jsonpath/Criteria2.java
  28. 48
      json-path/src/main/java/com/jayway/jsonpath/Filter.java
  29. 54
      json-path/src/main/java/com/jayway/jsonpath/Filter2.java
  30. 27
      json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java
  31. 1066
      json-path/src/main/java/com/jayway/jsonpath/JsonModel.java
  32. 137
      json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
  33. 4
      json-path/src/main/java/com/jayway/jsonpath/ParseContext.java
  34. 9
      json-path/src/main/java/com/jayway/jsonpath/Predicate.java
  35. 22
      json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
  36. 2
      json-path/src/main/java/com/jayway/jsonpath/Transformer.java
  37. 101
      json-path/src/main/java/com/jayway/jsonpath/internal/Cache.java
  38. 51
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java
  39. 24
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
  40. 159
      json-path/src/main/java/com/jayway/jsonpath/internal/Parser.java
  41. 191
      json-path/src/main/java/com/jayway/jsonpath/internal/PathFormalizer.java
  42. 79
      json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java
  43. 285
      json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java
  44. 101
      json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java
  45. 201
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java
  46. 155
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java
  47. 51
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayQueryFilter.java
  48. 136
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java
  49. 85
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterFactory.java
  50. 72
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasPathFilter.java
  51. 46
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java
  52. 70
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java
  53. 62
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java
  54. 57
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java
  55. 243
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java
  56. 155
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ArrayPathToken.java
  57. 51
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/CompiledPath.java
  58. 63
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/EvaluationContextImpl.java
  59. 74
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/FilterPathToken.java
  60. 530
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathCompiler.java
  61. 108
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathToken.java
  62. 41
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PropertyPathToken.java
  63. 66
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/RootPathToken.java
  64. 175
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ScanPathToken.java
  65. 31
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/WildcardPathToken.java
  66. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java
  67. 35
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonProvider.java
  68. 8
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JsonSmartJsonProvider.java
  69. 29
      json-path/src/main/java/com/jayway/jsonpath/spi/MappingProvider.java
  70. 54
      json-path/src/main/java/com/jayway/jsonpath/spi/MappingProviderFactory.java
  71. 16
      json-path/src/main/java/com/jayway/jsonpath/spi/compiler/EvaluationContext.java
  72. 15
      json-path/src/main/java/com/jayway/jsonpath/spi/compiler/Path.java
  73. 4
      json-path/src/main/java/com/jayway/jsonpath/spi/compiler/PathCompiler.java
  74. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/http/HttpProvider.java
  75. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/http/HttpProviderFactory.java
  76. 3
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java
  77. 6
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProviderFactory.java
  78. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/json/Mode.java
  79. 4
      json-path/src/test/java/com/jayway/jsonpath/ArraySlicingTest.java
  80. 181
      json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java
  81. 77
      json-path/src/test/java/com/jayway/jsonpath/DeepScanTest.java
  82. 57
      json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java
  83. 388
      json-path/src/test/java/com/jayway/jsonpath/Filter2Test.java
  84. 279
      json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
  85. 5
      json-path/src/test/java/com/jayway/jsonpath/HttpProviderTest.java
  86. 115
      json-path/src/test/java/com/jayway/jsonpath/IssuesTest.java
  87. 101
      json-path/src/test/java/com/jayway/jsonpath/JsonModelChainedCallsTest.java
  88. 143
      json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java
  89. 286
      json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java
  90. 116
      json-path/src/test/java/com/jayway/jsonpath/JsonModelSubModelTest.java
  91. 135
      json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java
  92. 8
      json-path/src/test/java/com/jayway/jsonpath/JsonPathFilterTest.java
  93. 34
      json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java
  94. 16
      json-path/src/test/java/com/jayway/jsonpath/JsonProviderTest.java
  95. 20
      json-path/src/test/java/com/jayway/jsonpath/MultiAttributeTest.java
  96. 3
      json-path/src/test/java/com/jayway/jsonpath/NullHandlingTest.java
  97. 156
      json-path/src/test/java/com/jayway/jsonpath/PathTest.java
  98. 30
      json-path/src/test/java/com/jayway/jsonpath/Runner.java
  99. 2
      json-path/src/test/java/com/jayway/jsonpath/internal/ArrayIndexFilterTest.java
  100. 88
      json-path/src/test/java/com/jayway/jsonpath/internal/ArrayPathTokenTest.java
  101. Some files were not shown because too many files have changed in this diff Show More

3
json-path-assert/src/main/java/com/jayway/jsonassert/JsonAssert.java

@ -3,8 +3,7 @@ package com.jayway.jsonassert;
import com.jayway.jsonassert.impl.JsonAsserterImpl;
import com.jayway.jsonassert.impl.matcher.*;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import org.hamcrest.Matcher;
import java.io.*;

20
json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java

@ -2,8 +2,11 @@ package com.jayway.jsonassert.impl;
import com.jayway.jsonassert.JsonAsserter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import org.hamcrest.Matcher;
import static java.lang.String.format;
@ -68,9 +71,13 @@ public class JsonAsserterImpl implements JsonAsserter {
public JsonAsserter assertNotDefined(String path) {
try {
Object o = JsonPath.read(jsonObject, path);
//Object o = JsonPath.read(jsonObject, path);
Configuration c = Configuration.builder().options(Option.THROW_ON_MISSING_PROPERTY).build();
JsonPath.using(c).parse(jsonObject).read(path);
throw new AssertionError(format("Document contains the path <%s> but was expected not to.", path));
} catch (InvalidPathException e) {
} catch (PathNotFoundException e) {
}
return this;
}
@ -78,9 +85,14 @@ public class JsonAsserterImpl implements JsonAsserter {
@Override
public JsonAsserter assertNotDefined(String path, String message) {
try {
Object o = JsonPath.read(jsonObject, path);
//Object o = JsonPath.read(jsonObject, path);
Configuration c = Configuration.builder().options(Option.THROW_ON_MISSING_PROPERTY).build();
JsonPath.using(c).parse(jsonObject).read(path);
throw new AssertionError(format("Document contains the path <%s> but was expected not to.", path));
} catch (InvalidPathException e) {
} catch (PathNotFoundException e) {
}
return this;
}

24
json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java

@ -49,7 +49,10 @@ public class JsonAssertTest {
" }\n" +
"}";
@Test
public void invalid_path() throws Exception {
with(JSON).assertThat("$.store.book[*].fooBar", collectionWithSize(equalTo(4)));
}
@Test(expected = AssertionError.class)
public void failed_error_message() throws Exception {
@ -112,7 +115,7 @@ public class JsonAssertTest {
with(JSON).assertThat("$.store.book[0]", hasEntry("category", "reference"))
.assertThat("$.store.book[0]", hasEntry("title", "Sayings of the Century"))
.and()
.assertThat("$..book[0]", hasEntry("category", "reference"))
.assertThat("$..book[0]", is(collectionWithSize(equalTo(1))))
.and()
.assertThat("$.store.book[0]", mapContainingKey(equalTo("category")))
.and()
@ -121,7 +124,7 @@ public class JsonAssertTest {
with(JSON).assertThat("$.['store'].['book'][0]", hasEntry("category", "reference"))
.assertThat("$.['store'].['book'][0]", hasEntry("title", "Sayings of the Century"))
.and()
.assertThat("$..['book'][0]", hasEntry("category", "reference"))
.assertThat("$..['book'][0]", is(collectionWithSize(equalTo(1))))
.and()
.assertThat("$.['store'].['book'][0]", mapContainingKey(equalTo("category")))
.and()
@ -150,16 +153,23 @@ public class JsonAssertTest {
}
*/
@Test
public void invalid_path() throws Exception {
with(JSON).assertThat("$.store.book[*].fooBar", emptyCollection());
}
@Test
public void path_including_wildcard_path_followed_by_another_path_concatenates_results_to_list() throws Exception {
with(getResourceAsStream("lotto.json")).assertThat("lotto.winners[*].winnerId", hasItems(23, 54));
}
@Test
public void testNotDefined() throws Exception {
JsonAsserter asserter = JsonAssert.with("{\"foo\":\"bar\"}");
asserter.assertEquals("$.foo", "bar"); // pass
asserter.assertEquals("$foo", "bar"); // pass
asserter.assertNotDefined("$.xxx"); // fail but should be pass
asserter.assertNotDefined("$xxx"); // fail but should be pass
}
private InputStream getResourceAsStream(String resourceName) {
return getClass().getClassLoader().getResourceAsStream(resourceName);

120
json-path-web-test/pom.xml

@ -0,0 +1,120 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-parent</artifactId>
<version>0.9.2-SNAPSHOT</version>
</parent>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-web-test</artifactId>
<version>0.9.2-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<gatling-jsonpath.version>0.4.0</gatling-jsonpath.version>
<boon.version>0.13</boon.version>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-mustache</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.9.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.fastjson</groupId>
<artifactId>boon</artifactId>
<version>${boon.version}</version>
</dependency>
<dependency>
<groupId>com.nebhale.jsonpath</groupId>
<artifactId>jsonpath</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>io.gatling</groupId>
<artifactId>jsonpath_2.10</artifactId>
<version>${gatling-jsonpath.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>com.jayway.oauth2.example.boot.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<onejarVersion>0.97</onejarVersion>
<attachToBuild>true</attachToBuild>
<classifier>onejar</classifier>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

131
json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Bench.java

@ -0,0 +1,131 @@
package com.jayway.jsonpath.web.bench;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.internal.spi.json.JacksonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import io.gatling.jsonpath.JsonPath$;
import org.boon.json.JsonParser;
import org.boon.json.ObjectMapper;
import org.boon.json.implementation.JsonParserCharArray;
import org.boon.json.implementation.ObjectMapperImpl;
import scala.collection.Iterator;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
public class Bench {
protected final String json;
protected final String path;
private final boolean value;
public Bench(String json, String path, boolean value) {
this.json = json;
this.path = path;
this.value = value;
}
public Result runJayway() {
String result = null;
String error = null;
long time;
Object res = null;
long now = System.currentTimeMillis();
try {
if(value) {
res = JsonPath.parse(json).read(path);
} else {
res = JsonPath.parse(json).readPathList(path);
}
} catch (Exception e){
error = getError(e);
} finally {
time = System.currentTimeMillis() - now;
if(res instanceof String) {
result = "\"" + res + "\"";
} else if(res instanceof Number) {
result = res.toString();
} else if(res instanceof Boolean){
result = res.toString();
} else {
result = res != null ? JsonProviderFactory.createProvider().toJson(res) : null;
}
return new Result("jayway", time, result, error);
}
}
public Result runBoon() {
String result = null;
String error = null;
long time;
Iterator<Object> query = null;
long now = System.currentTimeMillis();
try {
if(!value){
throw new UnsupportedOperationException("Not supported!");
}
io.gatling.jsonpath.JsonPath jsonPath = JsonPath$.MODULE$.compile(path).right().get();
JsonParser jsonParser = new JsonParserCharArray();
Object jsonModel = jsonParser.parse(json);
query = jsonPath.query(jsonModel);
} catch (Exception e){
error = getError(e);
} finally {
time = System.currentTimeMillis() - now;
if(query != null) {
List<Object> res = new ArrayList<Object>();
while (query.hasNext()) {
res.add(query.next());
}
ObjectMapper mapper = new ObjectMapperImpl();
result = mapper.toJson(res);
}
return new Result("boon", time, result, error);
}
}
public Result runNebhale() {
String result = null;
String error = null;
long time;
Object res = null;
JacksonProvider jacksonProvider = new JacksonProvider();
long now = System.currentTimeMillis();
try {
if(!value){
throw new UnsupportedOperationException("Not supported!");
}
com.nebhale.jsonpath.JsonPath compiled = com.nebhale.jsonpath.JsonPath.compile(path);
res = compiled.read(json, Object.class);
} catch (Exception e){
error = getError(e);
} finally {
time = System.currentTimeMillis() - now;
result = res!=null? jacksonProvider.toJson(res):null;
return new Result("nebhale", time, result, error);
}
}
public List<Result> runAll(){
return asList(runJayway(), runBoon(), runNebhale());
}
private String getError(Exception e){
String ex = e.getMessage();
if(ex == null || ex.trim().isEmpty()){
ex = "Undefined error";
}
return ex;
}
}

22
json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Result.java

@ -0,0 +1,22 @@
package com.jayway.jsonpath.web.bench;
import com.jayway.jsonpath.internal.JsonFormatter;
import java.util.List;
public class Result {
public final String provider;
public final String active;
public final long time;
public final String result;
public final String error;
public Result(String provider, long time, String result, String error) {
this.provider = provider;
this.active = provider == "jayway" ? "active" : "";
this.time = time;
this.result = result != null ? JsonFormatter.prettyPrint(result) : result;
this.error = error;
}
}

58
json-path-web-test/src/main/java/com/jayway/jsonpath/web/boot/Main.java

@ -0,0 +1,58 @@
package com.jayway.jsonpath.web.boot;
import static org.eclipse.jetty.servlet.ServletContextHandler.NO_SESSIONS;
import java.io.IOException;
import com.jayway.jsonpath.web.resource.IndexResource;
import com.jayway.jsonpath.web.resource.StaticResource;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.mustache.MustacheMvcFeature;
import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
public static void main(String[] args) throws Exception {
Server s = new Server();
s.setConnectors(new Connector[] { createConnector(s) });
ServletContextHandler context = new ServletContextHandler(NO_SESSIONS);
context.setContextPath("/");
ServletHolder servletHolder = new ServletHolder(createJerseyServlet());
servletHolder.setInitOrder(1);
context.addServlet(servletHolder, "/*");
s.setHandler(context);
s.start();
s.join();
}
private static ServerConnector createConnector(Server s){
ServerConnector connector = new ServerConnector(s);
connector.setHost("localhost");
connector.setPort(8080);
return connector;
}
private static ServletContainer createJerseyServlet() throws IOException {
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.property(MustacheMvcFeature.TEMPLATE_BASE_PATH, "templates");
resourceConfig.register(MustacheMvcFeature.class);
resourceConfig.register(JacksonFeature.class);
resourceConfig.register(new IndexResource());
resourceConfig.register(new StaticResource());
return new ServletContainer(resourceConfig);
}
}

96
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java

@ -0,0 +1,96 @@
package com.jayway.jsonpath.web.resource;
import com.jayway.jsonpath.web.bench.Bench;
import com.jayway.jsonpath.web.bench.Result;
import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.server.mvc.Viewable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Arrays.asList;
@Path("")
@Produces(MediaType.TEXT_HTML)
public class IndexResource {
private static final Logger logger = LoggerFactory.getLogger(IndexResource.class);
public final static Map<String, String> TEMPLATES = loadTemplates();
@GET
public Viewable get(@QueryParam("template") @DefaultValue("goessner") String template){
return createView(TEMPLATES.get(template), "$.store.book[0].title", true, template, null);
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Viewable post(@FormParam("json") String json,
@FormParam("path") String path,
@FormParam("type") String type,
@FormParam("template") String template){
boolean value = "VALUE".equalsIgnoreCase(type);
return createView(json, path, value, template, new Bench(json, path, value).runAll());
}
private Viewable createView(String json, String path, boolean value, String selectedTemplate, List<Result> results){
Map<String, Object> res = new HashMap<String, Object>();
res.put("results", results);
res.put("json", json);
res.put("path", path);
res.put("value-checked", value?"checked":"");
res.put("path-checked", (!value)?"checked":"");
res.put("templates", asList(new Template("goessner", "goessner", selectedTemplate), new Template("twitter" , "twitter", selectedTemplate), new Template("webapp", "webapp", selectedTemplate), new Template("20k", "20k", selectedTemplate)));
return new Viewable("/index", res);
}
private static Map<String, String> loadTemplates(){
try {
String goessner = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/goessner.json"), "UTF-8");
String twitter = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/twitter.json"));
String webapp = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/webxml.json"));
String twentyK = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/20k.json"));
Map<String, String> templates = new HashMap<String, String>();
templates.put("goessner", goessner);
templates.put("twitter", twitter);
templates.put("webapp", webapp);
templates.put("20k", twentyK);
return templates;
} catch (Exception e){
throw new RuntimeException(e);
}
}
private static class Template {
public final String value;
public final String name;
public final String selected;
private Template(String value, String name, String selectedValue) {
this.value = value;
this.name = name;
this.selected = value.equalsIgnoreCase(selectedValue)?"selected":"";
}
}
}

34
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/StaticResource.java

@ -0,0 +1,34 @@
package com.jayway.jsonpath.web.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import java.io.InputStream;
@Path("/static/")
public class StaticResource {
@GET
@Path("fonts/{resource}")
//@Produces("text/javascript")
public InputStream getFonts(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("fonts/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("js/{resource}")
@Produces("text/javascript")
public InputStream getJs(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("js/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("css/{resource}")
@Produces("text/css")
public InputStream getCss(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("css/" + uriInfo.getPathParameters().getFirst("resource"));
}
}

5785
json-path-web-test/src/main/resources/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

1
json-path-web-test/src/main/resources/css/bootstrap.css.map

File diff suppressed because one or more lines are too long

BIN
json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.eot

Binary file not shown.

229
json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.svg

@ -0,0 +1,229 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
<font-face units-per-em="1200" ascent="960" descent="-240" />
<missing-glyph horiz-adv-x="500" />
<glyph />
<glyph />
<glyph unicode="&#xd;" />
<glyph unicode=" " />
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
<glyph unicode="&#xa0;" />
<glyph unicode="&#x2000;" horiz-adv-x="652" />
<glyph unicode="&#x2001;" horiz-adv-x="1304" />
<glyph unicode="&#x2002;" horiz-adv-x="652" />
<glyph unicode="&#x2003;" horiz-adv-x="1304" />
<glyph unicode="&#x2004;" horiz-adv-x="434" />
<glyph unicode="&#x2005;" horiz-adv-x="326" />
<glyph unicode="&#x2006;" horiz-adv-x="217" />
<glyph unicode="&#x2007;" horiz-adv-x="217" />
<glyph unicode="&#x2008;" horiz-adv-x="163" />
<glyph unicode="&#x2009;" horiz-adv-x="260" />
<glyph unicode="&#x200a;" horiz-adv-x="72" />
<glyph unicode="&#x202f;" horiz-adv-x="260" />
<glyph unicode="&#x205f;" horiz-adv-x="326" />
<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 62 KiB

BIN
json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.ttf

Binary file not shown.

BIN
json-path-web-test/src/main/resources/fonts/glyphicons-halflings-regular.woff

Binary file not shown.

1951
json-path-web-test/src/main/resources/js/bootstrap.js vendored

File diff suppressed because it is too large Load Diff

87
json-path-web-test/src/main/resources/js/jsonpath-0.8.0.js

@ -0,0 +1,87 @@
/* JSONPath 0.8.0 - XPath for JSON
*
* Copyright (c) 2007 Stefan Goessner (goessner.net)
* Licensed under the MIT (MIT-LICENSE.txt) licence.
*/
function jsonPath(obj, expr, arg) {
var P = {
resultType: arg && arg.resultType || "VALUE",
result: [],
normalize: function(expr) {
var subx = [];
return expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";})
.replace(/'?\.'?|\['?/g, ";")
.replace(/;;;|;;/g, ";..;")
.replace(/;$|'?\]|'$/g, "")
.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
},
asPath: function(path) {
var x = path.split(";"), p = "$";
for (var i=1,n=x.length; i<n; i++)
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
return p;
},
store: function(p, v) {
if (p) P.result[P.result.length] = P.resultType == "PATH" ? P.asPath(p) : v;
return !!p;
},
trace: function(expr, val, path) {
if (expr) {
var x = expr.split(";"), loc = x.shift();
x = x.join(";");
if (val && val.hasOwnProperty(loc))
P.trace(x, val[loc], path + ";" + loc);
else if (loc === "*")
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); });
else if (loc === "..") {
P.trace(x, val, path);
P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); });
}
else if (/,/.test(loc)) { // [name1,name2,...]
for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
P.trace(s[i]+";"+x, val, path);
}
else if (/^\(.*?\)$/.test(loc)) // [(expr)]
P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path);
else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m)) P.trace(m+";"+x,v,p); });
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] phyton slice syntax
P.slice(loc, x, val, path);
}
else
P.store(path, val);
},
walk: function(loc, expr, val, path, f) {
if (val instanceof Array) {
for (var i=0,n=val.length; i<n; i++)
if (i in val)
f(i,loc,expr,val,path);
}
else if (typeof val === "object") {
for (var m in val)
if (val.hasOwnProperty(m))
f(m,loc,expr,val,path);
}
},
slice: function(loc, expr, val, path) {
if (val instanceof Array) {
var len=val.length, start=0, end=len, step=1;
loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
for (var i=start; i<end; i+=step)
P.trace(i+";"+expr, val, path);
}
},
eval: function(x, _v, _vname) {
try { return $ && _v && eval(x.replace(/@/g, "_v")); }
catch(e) { throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/@/g, "_v").replace(/\^/g, "_a")); }
}
};
var $ = obj;
if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) {
P.trace(P.normalize(expr).replace(/^\$;/,""), obj, "$");
return P.result.length ? P.result : false;
}
}

926
json-path-web-test/src/main/resources/json/20k.json

@ -0,0 +1,926 @@
[
{
"id": 0,
"guid": "d7c8d5e2-cfdc-43b9-9bd4-15e8fd344157",
"isActive": true,
"balance": "$3,772.00",
"picture": "http://placehold.it/32x32",
"age": 35,
"name": "Snow Rodriguez",
"gender": "male",
"company": "Applideck",
"email": "snowrodriguez@applideck.com",
"phone": "+1 (867) 551-3944",
"address": "548 Maple Avenue, Russellville, Pennsylvania, 2467",
"about": "Ex aute adipisicing incididunt labore est magna aliquip non consequat fugiat nostrud ex. Occaecat commodo irure ut mollit veniam fugiat esse esse laboris velit officia. Duis cillum aute ipsum sunt elit irure laborum nostrud. Dolor aliquip reprehenderit voluptate enim cupidatat nisi cillum enim quis aute fugiat id consequat.\r\n",
"registered": "1992-04-24T19:03:08 -02:00",
"latitude": -69.347636,
"longitude": 92.197293,
"tags": [
"enim",
"culpa",
"proident",
"duis",
"aute",
"tempor",
"anim"
],
"friends": [
{
"id": 0,
"name": "Garrison Tillman"
},
{
"id": 1,
"name": "Shawn Holman"
},
{
"id": 2,
"name": "Amy Guerra"
}
],
"randomArrayItem": "lemon"
},
{
"id": 1,
"guid": "2b7e2b0a-288f-404e-9fd0-ad2064cc49f4",
"isActive": true,
"balance": "$3,046.00",
"picture": "http://placehold.it/32x32",
"age": 24,
"name": "Phyllis Calhoun",
"gender": "female",
"company": "Olucore",
"email": "phylliscalhoun@olucore.com",
"phone": "+1 (890) 443-2093",
"address": "355 Brighton Avenue, Shrewsbury, Washington, 8719",
"about": "Excepteur magna culpa do exercitation anim cillum ad proident nostrud ex. Voluptate sint pariatur nisi magna et cillum Lorem Lorem in deserunt eu. Proident dolor laborum nisi anim. Veniam aliqua nulla minim adipisicing magna exercitation veniam sint ea minim nulla.\r\n",
"registered": "1996-12-05T15:20:59 -01:00",
"latitude": -19.65876,
"longitude": 168.158924,
"tags": [
"ad",
"exercitation",
"laboris",
"id",
"incididunt",
"nisi",
"non"
],
"friends": [
{
"id": 0,
"name": "Serena Collins"
},
{
"id": 1,
"name": "Carolina Anthony"
},
{
"id": 2,
"name": "Kendra Avery"
}
],
"randomArrayItem": "lemon"
},
{
"id": 2,
"guid": "523d89ac-63aa-4fac-9352-07cbd8f21a6a",
"isActive": true,
"balance": "$1,242.00",
"picture": "http://placehold.it/32x32",
"age": 38,
"name": "Lindsay Stuart",
"gender": "female",
"company": "Papricut",
"email": "lindsaystuart@papricut.com",
"phone": "+1 (859) 589-3940",
"address": "688 Wyckoff Street, Carrizo, California, 6999",
"about": "Do exercitation labore in excepteur laborum eiusmod enim officia proident nulla veniam. Do Lorem dolor eiusmod proident qui in consequat aliqua. Lorem nulla id consequat ea enim ad id exercitation dolor ad dolore.\r\n",
"registered": "1997-01-09T23:08:18 -01:00",
"latitude": 87.910568,
"longitude": 163.037238,
"tags": [
"qui",
"mollit",
"aute",
"et",
"veniam",
"elit",
"labore"
],
"friends": [
{
"id": 0,
"name": "Bullock Hutchinson"
},
{
"id": 1,
"name": "Guthrie Clark"
},
{
"id": 2,
"name": "Elena Delaney"
}
],
"randomArrayItem": "cherry"
},
{
"id": 3,
"guid": "bc7a2767-94e5-4ebc-8f9d-ead42c3e0107",
"isActive": true,
"balance": "$2,533.00",
"picture": "http://placehold.it/32x32",
"age": 33,
"name": "Mcmahon Adams",
"gender": "male",
"company": "Balooba",
"email": "mcmahonadams@balooba.com",
"phone": "+1 (984) 475-3671",
"address": "880 Pilling Street, Omar, Minnesota, 8563",
"about": "Excepteur incididunt commodo veniam enim esse magna. Exercitation dolor cupidatat consequat irure. Ex duis dolor non nostrud duis aliqua enim labore aliquip. Ad qui reprehenderit aute aliquip duis magna aliquip nisi nulla. Cillum ad sint reprehenderit officia id nostrud cillum excepteur cillum ea labore ullamco esse. Laboris sint ut id incididunt Lorem non reprehenderit adipisicing. Id sint laboris deserunt ea.\r\n",
"registered": "2005-03-01T02:26:24 -01:00",
"latitude": 6.359315,
"longitude": 33.053339,
"tags": [
"Lorem",
"ex",
"dolore",
"pariatur",
"officia",
"ipsum",
"dolore"
],
"friends": [
{
"id": 0,
"name": "Mollie Wilcox"
},
{
"id": 1,
"name": "Alta Hall"
},
{
"id": 2,
"name": "Paulette Pollard"
}
],
"randomArrayItem": "lemon"
},
{
"id": 4,
"guid": "9bbe7981-9e4c-4140-a7f4-be8fcae8ae18",
"isActive": true,
"balance": "$2,731.00",
"picture": "http://placehold.it/32x32",
"age": 29,
"name": "Nanette Butler",
"gender": "female",
"company": "Nikuda",
"email": "nanettebutler@nikuda.com",
"phone": "+1 (989) 498-2116",
"address": "637 Colby Court, Whitewater, Vermont, 1992",
"about": "Magna Lorem sit sit duis. Aliqua eiusmod dolor enim est duis nulla in eu deserunt commodo. Sit laboris deserunt sint duis reprehenderit in sunt excepteur proident. Elit ad aliquip deserunt in ad occaecat id elit non commodo adipisicing ullamco magna.\r\n",
"registered": "1995-04-25T05:22:25 -02:00",
"latitude": -45.069546,
"longitude": 83.01566,
"tags": [
"est",
"in",
"nulla",
"ea",
"dolore",
"aliqua",
"deserunt"
],
"friends": [
{
"id": 0,
"name": "Noble Rodgers"
},
{
"id": 1,
"name": "Haley Mayer"
},
{
"id": 2,
"name": "Hudson Gentry"
}
],
"randomArrayItem": "lemon"
},
{
"id": 5,
"guid": "f0449f33-5c39-4a94-a114-e96d466cc9a8",
"isActive": true,
"balance": "$1,769.00",
"picture": "http://placehold.it/32x32",
"age": 26,
"name": "Miranda Thomas",
"gender": "male",
"company": "Softmicro",
"email": "mirandathomas@softmicro.com",
"phone": "+1 (870) 591-2118",
"address": "503 Linden Street, Jackpot, Rhode Island, 419",
"about": "Consequat tempor esse pariatur minim magna ut ut dolor officia anim. Mollit mollit tempor do dolor ad aute proident commodo sit ea minim. Eu et laborum est in. Non exercitation est deserunt do mollit tempor duis. Nisi eu nulla ea cillum minim officia et duis quis sint. Consequat velit cupidatat Lorem sunt do do quis et ullamco. Elit eiusmod consectetur ullamco ea amet sint aute quis ipsum.\r\n",
"registered": "2010-10-07T07:31:46 -02:00",
"latitude": -28.329413,
"longitude": -17.80299,
"tags": [
"fugiat",
"reprehenderit",
"adipisicing",
"culpa",
"quis",
"pariatur",
"deserunt"
],
"friends": [
{
"id": 0,
"name": "Brewer Norton"
},
{
"id": 1,
"name": "Ramona Jacobs"
},
{
"id": 2,
"name": "Russo Hewitt"
}
],
"randomArrayItem": "apple"
},
{
"id": 6,
"guid": "18fb0572-e2b8-4f47-bd71-dc9349396227",
"isActive": true,
"balance": "$3,081.00",
"picture": "http://placehold.it/32x32",
"age": 30,
"name": "Ada Potter",
"gender": "female",
"company": "Melbacor",
"email": "adapotter@melbacor.com",
"phone": "+1 (913) 474-2861",
"address": "947 Sumner Place, Haena, North Dakota, 685",
"about": "Nostrud amet id id qui. Reprehenderit officia duis ad aute ipsum eiusmod excepteur Lorem voluptate. Cillum laborum cillum aliquip duis reprehenderit amet sint non nulla in culpa irure veniam aliqua.\r\n",
"registered": "2008-09-26T03:40:28 -02:00",
"latitude": -11.153539,
"longitude": 115.382908,
"tags": [
"laboris",
"proident",
"dolore",
"sunt",
"ut",
"irure",
"dolor"
],
"friends": [
{
"id": 0,
"name": "Bethany Carroll"
},
{
"id": 1,
"name": "Moody Andrews"
},
{
"id": 2,
"name": "Trujillo Hester"
}
],
"randomArrayItem": "cherry"
},
{
"id": 7,
"guid": "69cc1cdc-2953-4a00-84df-bed00120ab12",
"isActive": true,
"balance": "$2,520.00",
"picture": "http://placehold.it/32x32",
"age": 36,
"name": "Levine Deleon",
"gender": "male",
"company": "Dragbot",
"email": "levinedeleon@dragbot.com",
"phone": "+1 (979) 575-3162",
"address": "902 Elmwood Avenue, Caberfae, Delaware, 4651",
"about": "Laboris nulla velit dolor ex duis pariatur aute est. Incididunt incididunt laborum non culpa. Consequat elit ipsum et sint nisi dolore dolore nisi ut. Quis nostrud ex ad duis. Enim aliquip pariatur deserunt amet est ullamco in. Dolor sunt deserunt id deserunt labore reprehenderit enim ut in consectetur laboris incididunt in nisi. Ipsum sint in ipsum minim ipsum proident commodo excepteur cillum.\r\n",
"registered": "2000-08-15T05:06:23 -02:00",
"latitude": -48.334821,
"longitude": 66.328798,
"tags": [
"nostrud",
"labore",
"ipsum",
"reprehenderit",
"mollit",
"consequat",
"adipisicing"
],
"friends": [
{
"id": 0,
"name": "Jolene Vang"
},
{
"id": 1,
"name": "Diana Frost"
},
{
"id": 2,
"name": "Bobbi Franklin"
}
],
"randomArrayItem": "apple"
},
{
"id": 8,
"guid": "3a6bf80f-273e-40e9-b5b4-d6d7e07e76c6",
"isActive": false,
"balance": "$1,694.00",
"picture": "http://placehold.it/32x32",
"age": 32,
"name": "Sophia Duran",
"gender": "female",
"company": "Magmina",
"email": "sophiaduran@magmina.com",
"phone": "+1 (843) 415-3460",
"address": "133 Norfolk Street, Worcester, Virginia, 3631",
"about": "Lorem occaecat officia proident consectetur sint anim id sit anim. Deserunt veniam aute deserunt proident. Ut cillum aliquip deserunt ipsum Lorem est qui cupidatat. Ipsum irure ullamco do cillum duis est in officia et officia elit nisi dolore cillum. Occaecat eu ad pariatur ad Lorem incididunt exercitation nulla. Adipisicing id mollit labore incididunt eiusmod. Esse voluptate ad cupidatat est commodo velit velit laboris ad fugiat mollit.\r\n",
"registered": "2003-01-12T07:36:55 -01:00",
"latitude": 49.58874,
"longitude": 140.795001,
"tags": [
"nulla",
"officia",
"amet",
"irure",
"voluptate",
"exercitation",
"ad"
],
"friends": [
{
"id": 0,
"name": "Twila Holcomb"
},
{
"id": 1,
"name": "Katy Cruz"
},
{
"id": 2,
"name": "Winnie Savage"
}
],
"randomArrayItem": "apple"
},
{
"id": 9,
"guid": "bf01372f-e27c-4f56-9831-9599cc11a73a",
"isActive": true,
"balance": "$1,087.00",
"picture": "http://placehold.it/32x32",
"age": 37,
"name": "Boyd Tyson",
"gender": "male",
"company": "Skyplex",
"email": "boydtyson@skyplex.com",
"phone": "+1 (913) 438-2918",
"address": "966 Winthrop Street, Weogufka, Massachusetts, 2510",
"about": "Pariatur occaecat eiusmod incididunt elit irure sit enim proident et aute aliquip quis ea exercitation. Cillum et labore est anim sunt. Sint consectetur ullamco exercitation sit consequat laborum exercitation ea dolor deserunt. Proident fugiat ipsum voluptate commodo mollit pariatur commodo veniam eu ex duis nulla. Ex officia qui occaecat duis consectetur. Ullamco fugiat adipisicing quis Lorem velit laborum officia ex veniam id excepteur in.\r\n",
"registered": "2000-12-30T18:33:42 -01:00",
"latitude": 17.222712,
"longitude": 110.698092,
"tags": [
"esse",
"consequat",
"dolor",
"proident",
"Lorem",
"ex",
"ex"
],
"friends": [
{
"id": 0,
"name": "Stout Herring"
},
{
"id": 1,
"name": "Noemi Vincent"
},
{
"id": 2,
"name": "Johnnie Yates"
}
],
"randomArrayItem": "cherry"
},
{
"id": 10,
"guid": "ff535706-ea8c-44fe-b1aa-ae85c3e88931",
"isActive": false,
"balance": "$2,573.00",
"picture": "http://placehold.it/32x32",
"age": 34,
"name": "Lucille Juarez",
"gender": "female",
"company": "Essensia",
"email": "lucillejuarez@essensia.com",
"phone": "+1 (842) 518-3032",
"address": "976 Lexington Avenue, Jacumba, Tennessee, 2110",
"about": "Minim esse in nostrud et dolor ut dolore dolor. Eiusmod sint incididunt id dolore elit eu quis dolor. Reprehenderit occaecat reprehenderit minim aute tempor sit. Voluptate sunt eiusmod sit id cillum magna aliquip aliquip. Magna cillum qui id adipisicing irure quis laboris.\r\n",
"registered": "2002-08-18T00:54:13 -02:00",
"latitude": 23.945548,
"longitude": 34.181728,
"tags": [
"veniam",
"ex",
"aliquip",
"ex",
"ad",
"reprehenderit",
"et"
],
"friends": [
{
"id": 0,
"name": "Norma Weiss"
},
{
"id": 1,
"name": "Elnora Odom"
},
{
"id": 2,
"name": "Jennifer Puckett"
}
],
"randomArrayItem": "lemon"
},
{
"id": 11,
"guid": "30eb71bc-e76e-41eb-90db-b6607b2471b5",
"isActive": true,
"balance": "$3,019.00",
"picture": "http://placehold.it/32x32",
"age": 27,
"name": "Antonia Byers",
"gender": "female",
"company": "Pearlessa",
"email": "antoniabyers@pearlessa.com",
"phone": "+1 (986) 456-2695",
"address": "112 Montieth Street, Hegins, Arkansas, 614",
"about": "Consequat id Lorem pariatur sunt ea veniam anim aliquip amet duis. Minim id nulla est est cupidatat laboris commodo. Et eu magna commodo commodo esse ut deserunt cupidatat ea velit. Sint duis voluptate non amet ea laborum. Dolore ullamco ut Lorem aliquip pariatur laboris. Laborum deserunt Lorem sit eu elit duis exercitation proident sit proident.\r\n",
"registered": "2004-01-17T16:00:50 -01:00",
"latitude": -69.440764,
"longitude": -135.627868,
"tags": [
"adipisicing",
"voluptate",
"incididunt",
"laboris",
"veniam",
"commodo",
"velit"
],
"friends": [
{
"id": 0,
"name": "Melba Fields"
},
{
"id": 1,
"name": "Miles Holden"
},
{
"id": 2,
"name": "Lauren Goff"
}
],
"randomArrayItem": "apple"
},
{
"id": 12,
"guid": "5d1f9fd9-b3a6-4320-ba8a-cb9273bca3e9",
"isActive": false,
"balance": "$1,723.00",
"picture": "http://placehold.it/32x32",
"age": 28,
"name": "Wyatt Douglas",
"gender": "male",
"company": "Paragonia",
"email": "wyattdouglas@paragonia.com",
"phone": "+1 (885) 580-2488",
"address": "674 Gerritsen Avenue, Needmore, Michigan, 608",
"about": "Enim adipisicing ut proident occaecat cupidatat excepteur sint do id aute ad amet laboris est. Sit culpa consequat nisi sunt exercitation ullamco est commodo exercitation fugiat velit. Laboris et sit deserunt commodo exercitation nisi aliqua non incididunt id id. Tempor exercitation aute Lorem anim ad nulla dolor aliqua do dolore.\r\n",
"registered": "1991-09-02T02:08:08 -02:00",
"latitude": 66.105776,
"longitude": 91.843229,
"tags": [
"consectetur",
"sunt",
"ex",
"enim",
"labore",
"esse",
"ut"
],
"friends": [
{
"id": 0,
"name": "Mcpherson Velez"
},
{
"id": 1,
"name": "Cochran Bennett"
},
{
"id": 2,
"name": "Welch Glover"
}
],
"randomArrayItem": "cherry"
},
{
"id": 13,
"guid": "139ebd33-41d1-4a12-aaf0-e2957587ea9f",
"isActive": true,
"balance": "$1,838.00",
"picture": "http://placehold.it/32x32",
"age": 26,
"name": "Leah Downs",
"gender": "female",
"company": "Idealis",
"email": "leahdowns@idealis.com",
"phone": "+1 (878) 537-3328",
"address": "174 Herkimer Court, Hamilton, Indiana, 8465",
"about": "Elit deserunt ipsum exercitation dolor cillum excepteur culpa culpa ut sunt veniam. Elit non ut magna ea nostrud excepteur nisi aliquip pariatur. Veniam culpa officia ea nostrud minim et eiusmod. Sunt aliquip in non pariatur eu dolore aliquip magna. Velit exercitation et nisi deserunt exercitation voluptate Lorem enim elit fugiat adipisicing excepteur aliquip ut. Duis id reprehenderit ullamco commodo nulla nisi officia commodo occaecat sunt tempor veniam. Cillum minim do adipisicing cupidatat anim officia velit elit ea magna nisi do enim reprehenderit.\r\n",
"registered": "1988-08-25T19:07:19 -02:00",
"latitude": -73.977289,
"longitude": -116.135149,
"tags": [
"ex",
"et",
"non",
"commodo",
"cupidatat",
"cupidatat",
"nisi"
],
"friends": [
{
"id": 0,
"name": "Soto Brown"
},
{
"id": 1,
"name": "Henry Conrad"
},
{
"id": 2,
"name": "Marshall Wolf"
}
],
"randomArrayItem": "apple"
},
{
"id": 14,
"guid": "1082a62a-c042-4826-a50a-b5be72a07037",
"isActive": false,
"balance": "$3,349.00",
"picture": "http://placehold.it/32x32",
"age": 29,
"name": "Schneider Durham",
"gender": "male",
"company": "Memora",
"email": "schneiderdurham@memora.com",
"phone": "+1 (882) 421-2055",
"address": "166 Chauncey Street, Coultervillle, Idaho, 8121",
"about": "Aute laboris nisi elit do dolor tempor reprehenderit cillum esse non consectetur nostrud voluptate. Tempor mollit do dolor irure non in deserunt ut proident nisi cupidatat. Anim mollit labore quis nulla nostrud reprehenderit sit aliqua exercitation nisi.\r\n",
"registered": "2003-09-21T21:15:56 -02:00",
"latitude": -56.159995,
"longitude": 4.310579,
"tags": [
"adipisicing",
"ex",
"exercitation",
"aliquip",
"commodo",
"non",
"excepteur"
],
"friends": [
{
"id": 0,
"name": "Jo Lara"
},
{
"id": 1,
"name": "Merrill Gray"
},
{
"id": 2,
"name": "Jacobson Burris"
}
],
"randomArrayItem": "lemon"
},
{
"id": 15,
"guid": "b58c304c-cca9-482c-b2b5-810e8fa15ef6",
"isActive": true,
"balance": "$2,923.00",
"picture": "http://placehold.it/32x32",
"age": 30,
"name": "Shelton Burnett",
"gender": "male",
"company": "Geekola",
"email": "sheltonburnett@geekola.com",
"phone": "+1 (821) 501-3726",
"address": "117 Chase Court, Joes, Alabama, 774",
"about": "Non sit cupidatat laboris deserunt adipisicing nisi ipsum commodo. Labore duis sint eu dolor esse consectetur esse ullamco Lorem id nisi culpa sint. Cillum commodo incididunt occaecat reprehenderit enim aliquip velit. Sit voluptate dolore deserunt magna voluptate laborum fugiat ad. Voluptate ad aliqua ullamco eiusmod. Labore ut non ut reprehenderit enim non.\r\n",
"registered": "1992-10-02T12:42:44 -01:00",
"latitude": -58.765178,
"longitude": -155.109015,
"tags": [
"culpa",
"do",
"do",
"enim",
"minim",
"enim",
"nulla"
],
"friends": [
{
"id": 0,
"name": "Lillie Todd"
},
{
"id": 1,
"name": "Morales Crosby"
},
{
"id": 2,
"name": "Tracie Hamilton"
}
],
"randomArrayItem": "apple"
},
{
"id": 16,
"guid": "1a33e0ff-909e-4e31-b4f7-a6d0d0d72320",
"isActive": false,
"balance": "$1,693.00",
"picture": "http://placehold.it/32x32",
"age": 27,
"name": "Crane Livingston",
"gender": "male",
"company": "Enomen",
"email": "cranelivingston@enomen.com",
"phone": "+1 (990) 563-2727",
"address": "248 Elliott Place, Walland, New Jersey, 8005",
"about": "Culpa anim sunt esse commodo deserunt reprehenderit laboris commodo ullamco Lorem. Tempor veniam officia eiusmod excepteur pariatur quis excepteur qui dolore consequat. Dolore tempor duis occaecat deserunt aute elit ex quis do occaecat et.\r\n",
"registered": "2007-03-09T12:39:06 -01:00",
"latitude": 45.176807,
"longitude": -2.485176,
"tags": [
"ad",
"ea",
"in",
"consequat",
"aute",
"laborum",
"commodo"
],
"friends": [
{
"id": 0,
"name": "Katrina Hoover"
},
{
"id": 1,
"name": "Angeline Farmer"
},
{
"id": 2,
"name": "Perkins Haney"
}
],
"randomArrayItem": "apple"
},
{
"id": 17,
"guid": "e6e7cbf1-e991-4e7b-96b7-bef35f249ffd",
"isActive": true,
"balance": "$2,167.00",
"picture": "http://placehold.it/32x32",
"age": 21,
"name": "Bean Moody",
"gender": "male",
"company": "Terascape",
"email": "beanmoody@terascape.com",
"phone": "+1 (898) 582-2002",
"address": "773 Brighton Court, Kenwood, Missouri, 6928",
"about": "Id consequat cupidatat ex cupidatat eiusmod dolore ea incididunt sunt deserunt. Consequat dolor veniam amet incididunt Lorem exercitation dolore do velit tempor id culpa eiusmod. Occaecat esse est laboris nisi consectetur minim. Exercitation ea nostrud laboris aliqua consectetur aliquip nostrud dolor commodo. Elit officia quis in elit enim cupidatat sit sint deserunt dolore duis.\r\n",
"registered": "1997-10-19T10:30:44 -02:00",
"latitude": 48.493501,
"longitude": -53.665346,
"tags": [
"duis",
"proident",
"eu",
"dolor",
"occaecat",
"sit",
"eu"
],
"friends": [
{
"id": 0,
"name": "Beasley Mcmillan"
},
{
"id": 1,
"name": "Saundra Morales"
},
{
"id": 2,
"name": "Morrow Mcclure"
}
],
"randomArrayItem": "lemon"
},
{
"id": 18,
"guid": "53d4712a-aaad-4cf7-8de9-a0e2422a070c",
"isActive": true,
"balance": "$1,193.00",
"picture": "http://placehold.it/32x32",
"age": 20,
"name": "Hodges Lawson",
"gender": "male",
"company": "Medesign",
"email": "hodgeslawson@medesign.com",
"phone": "+1 (843) 453-3635",
"address": "216 Fairview Place, Balm, Louisiana, 5648",
"about": "Proident aliqua exercitation minim est. Esse veniam sunt dolore laborum dolor minim. Dolor id eiusmod fugiat qui anim incididunt occaecat pariatur non. Ea exercitation incididunt elit non eu.\r\n",
"registered": "2008-01-14T06:12:50 -01:00",
"latitude": 77.014486,
"longitude": 171.670465,
"tags": [
"dolor",
"ullamco",
"minim",
"sunt",
"laborum",
"dolor",
"ex"
],
"friends": [
{
"id": 0,
"name": "Mcconnell Hahn"
},
{
"id": 1,
"name": "King Baker"
},
{
"id": 2,
"name": "Virgie Holt"
}
],
"randomArrayItem": "cherry"
},
{
"id": 19,
"guid": "99db9ee5-bd4c-41f6-9f73-92f5644b7b97",
"isActive": true,
"balance": "$3,744.00",
"picture": "http://placehold.it/32x32",
"age": 40,
"name": "Lancaster Walton",
"gender": "male",
"company": "Codax",
"email": "lancasterwalton@codax.com",
"phone": "+1 (965) 409-3192",
"address": "646 Harwood Place, Bodega, New Hampshire, 606",
"about": "Proident nostrud enim consequat irure. Duis amet incididunt ex do quis consectetur nisi laboris est voluptate esse. Laboris consectetur esse ullamco nostrud aute fugiat ad dolore eiusmod. Sit commodo elit aute Lorem ad deserunt sit est Lorem reprehenderit dolor minim ex.\r\n",
"registered": "2011-03-05T16:51:53 -01:00",
"latitude": -67.193873,
"longitude": 45.464244,
"tags": [
"qui",
"ea",
"laborum",
"voluptate",
"occaecat",
"nisi",
"in"
],
"friends": [
{
"id": 0,
"name": "Zamora Trujillo"
},
{
"id": 1,
"name": "Latisha Fernandez"
},
{
"id": 2,
"name": "Mayo Harris"
}
],
"randomArrayItem": "apple"
},
{
"id": 20,
"guid": "d54147b7-09fe-4dfb-8828-a73a5d2654b9",
"isActive": true,
"balance": "$1,534.00",
"picture": "http://placehold.it/32x32",
"age": 36,
"name": "Lindsay Hawkins",
"gender": "male",
"company": "Isosphere",
"email": "lindsayhawkins@isosphere.com",
"phone": "+1 (957) 416-3291",
"address": "461 Conover Street, Epworth, Wyoming, 2303",
"about": "Enim amet sint minim pariatur aliquip proident fugiat consequat deserunt proident. Do excepteur Lorem velit sint proident ea aute eiusmod ipsum. Laborum id eiusmod do nostrud proident consequat eu fugiat elit nostrud nisi. Id aliqua est aliqua dolore ad id commodo est cillum in ipsum nostrud. Enim anim velit id adipisicing non exercitation dolore proident. Dolor sit amet commodo duis.\r\n",
"registered": "1991-07-10T19:55:25 -02:00",
"latitude": -71.393384,
"longitude": 129.718457,
"tags": [
"nostrud",
"reprehenderit",
"ea",
"elit",
"ipsum",
"cillum",
"nulla"
],
"friends": [
{
"id": 0,
"name": "Bartlett Shaw"
},
{
"id": 1,
"name": "Black Barron"
},
{
"id": 2,
"name": "Nona Mcgee"
}
],
"randomArrayItem": "apple"
},
{
"id": 21,
"guid": "d648f647-adaa-4bbe-9285-344a916f2241",
"isActive": true,
"balance": "$1,387.00",
"picture": "http://placehold.it/32x32",
"age": 22,
"name": "Jewel Mccoy",
"gender": "female",
"company": "Tetak",
"email": "jewelmccoy@tetak.com",
"phone": "+1 (931) 568-2889",
"address": "691 Putnam Avenue, Nettie, Arizona, 7175",
"about": "Enim proident occaecat culpa cupidatat exercitation aute ullamco aliquip id in et ea sit enim. Id Lorem veniam minim laborum labore minim fugiat eu anim. Eiusmod esse magna sunt ea. Proident deserunt dolore consequat mollit culpa laboris. Tempor veniam fugiat eu aliqua. Sint velit consequat in tempor velit non ullamco consequat duis dolore mollit cupidatat in consectetur. Culpa consequat et non nostrud amet fugiat ea do sit est reprehenderit incididunt aute.\r\n",
"registered": "2013-09-21T12:52:13 -02:00",
"latitude": 12.704629,
"longitude": 96.065025,
"tags": [
"irure",
"aliqua",
"excepteur",
"elit",
"occaecat",
"nostrud",
"dolore"
],
"friends": [
{
"id": 0,
"name": "Ida Harvey"
},
{
"id": 1,
"name": "Ora Santana"
},
{
"id": 2,
"name": "Lynnette Bullock"
}
],
"randomArrayItem": "lemon"
}
]

50469
json-path-web-test/src/main/resources/json/citm_catalog.json

File diff suppressed because it is too large Load Diff

1
json-path-web-test/src/main/resources/json/goessner.json

@ -0,0 +1 @@
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "display-price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "display-price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "display-price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "display-price": 22.99 } ], "bicycle": { "foo": "baz", "color": "red", "display-price": 19.95, "foo:bar": "fooBar", "dot.notation": "new", "dash-notation": "dashes" } }, "foo": "bar", "@id": "ID" }

298
json-path-web-test/src/main/resources/json/twitter.json

@ -0,0 +1,298 @@
{"completed_in": 0.072, "max_id": 336448826225328128, "max_id_str": "336448826225328128", "next_page": "?page=2&max_id=336448826225328128&q=gatling", "page": 1, "query": "gatling", "refresh_url": "?since_id=336448826225328128&q=gatling", "results": [
{
"created_at": "Mon, 20 May 2013 11:50:25 +0000",
"from_user": "anna_gatling",
"from_user_id": 1237619628,
"from_user_id_str": "1237619628",
"from_user_name": "Anna Gatling",
"geo": null,
"id": 336448826225328128,
"id_str": "336448826225328128",
"iso_language_code": "en",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3402698946\/bebb3fcb7a7a3977a69c30797cfce5db_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3402698946\/bebb3fcb7a7a3977a69c30797cfce5db_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/iphone&quot;&gt;Twitter for iPhone&lt;\/a&gt;",
"text": "Last Monday of 6th grade yayyyyy"
},
{
"created_at": "Mon, 20 May 2013 11:49:40 +0000",
"from_user": "ddnn_",
"from_user_id": 482530993,
"from_user_id_str": "482530993",
"from_user_name": "D'\u306e\u7d14\u60c5",
"geo": null,
"id": 336448635355144192,
"id_str": "336448635355144192",
"iso_language_code": "tl",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3676715268\/74fa7666ffce02296cc7dfa25f6a8f9c_normal.png",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3676715268\/74fa7666ffce02296cc7dfa25f6a8f9c_normal.png",
"source": "&lt;a href=&quot;http:\/\/m.ubersocial.com&quot;&gt;UberSocial Mobile&lt;\/a&gt;",
"text": "@Arc46_ gatling gun... as in minigun or what?",
"to_user": "Arc46_",
"to_user_id": 336528266,
"to_user_id_str": "336528266",
"to_user_name": "SamuelJunioPradipta",
"in_reply_to_status_id": 336448069233172480,
"in_reply_to_status_id_str": "336448069233172480"
},
{
"created_at": "Mon, 20 May 2013 11:48:56 +0000",
"from_user": "FonshudelSur",
"from_user_id": 300933633,
"from_user_id_str": "300933633",
"from_user_name": "Fonshu",
"geo": null,
"id": 336448452076634113,
"id_str": "336448452076634113",
"iso_language_code": "es",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3654066775\/8da1e0e3f2d9ef89f34ac66993bb8836_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3654066775\/8da1e0e3f2d9ef89f34ac66993bb8836_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/www.tweetdeck.com&quot;&gt;TweetDeck&lt;\/a&gt;",
"text": "@IsaraMiau Y tengo que currarme un cosplay para ir del patriota mecanizado con la gatling steampunk, que es DE LO MEJOR &lt;3",
"to_user": "FonshudelSur",
"to_user_id": 300933633,
"to_user_id_str": "300933633",
"to_user_name": "Fonshu",
"in_reply_to_status_id": 336448304835608576,
"in_reply_to_status_id_str": "336448304835608576"
},
{
"created_at": "Mon, 20 May 2013 11:47:25 +0000",
"from_user": "Arc46_",
"from_user_id": 336528266,
"from_user_id_str": "336528266",
"from_user_name": "SamuelJunioPradipta",
"geo": null,
"id": 336448069233172480,
"id_str": "336448069233172480",
"iso_language_code": "en",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3684084503\/2e880c5f9b9d7d6030d6d972feb9f5c4_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3684084503\/2e880c5f9b9d7d6030d6d972feb9f5c4_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/www.tweetdeck.com&quot;&gt;TweetDeck&lt;\/a&gt;",
"text": "Something like Gatling gun, Bazooka RT @ddnn_: what are you exactly trying to make?"
},
{
"created_at": "Mon, 20 May 2013 11:37:49 +0000",
"from_user": "anna_gatling",
"from_user_id": 1237619628,
"from_user_id_str": "1237619628",
"from_user_name": "Anna Gatling",
"geo": null,
"id": 336445653662191616,
"id_str": "336445653662191616",
"iso_language_code": "en",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3402698946\/bebb3fcb7a7a3977a69c30797cfce5db_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3402698946\/bebb3fcb7a7a3977a69c30797cfce5db_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/iphone&quot;&gt;Twitter for iPhone&lt;\/a&gt;",
"text": "Mondays&lt;"
},
{
"created_at": "Mon, 20 May 2013 11:29:57 +0000",
"from_user": "GATLING_FIGHTER",
"from_user_id": 1184500015,
"from_user_id_str": "1184500015",
"from_user_name": "M134 \u307f\u306b-\u304c\u3093",
"geo": null,
"id": 336443676270157826,
"id_str": "336443676270157826",
"iso_language_code": "ja",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3607829622\/68059740f01d6532bc876e2e7ffb84d0_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3607829622\/68059740f01d6532bc876e2e7ffb84d0_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/theworld09.com\/&quot;&gt;TheWorld\u2800&lt;\/a&gt;",
"text": "@Orz619 \u4f55\u3067\u3059\u3063\u3066\uff01\uff1f",
"to_user": "Orz619",
"to_user_id": 1393895851,
"to_user_id_str": "1393895851",
"to_user_name": "\u3050\u3063\u3055\u3093@\u9ed2\u732b\u306f\u53f7\u54ed\u3057\u3066\u3044\u307e\u3059\u3088\u3002",
"in_reply_to_status_id": 336443439870779394,
"in_reply_to_status_id_str": "336443439870779394"
},
{
"created_at": "Mon, 20 May 2013 11:29:48 +0000",
"from_user": "GATLING_FIGHTER",
"from_user_id": 1184500015,
"from_user_id_str": "1184500015",
"from_user_name": "M134 \u307f\u306b-\u304c\u3093",
"geo": null,
"id": 336443634872360960,
"id_str": "336443634872360960",
"iso_language_code": "ja",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3607829622\/68059740f01d6532bc876e2e7ffb84d0_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3607829622\/68059740f01d6532bc876e2e7ffb84d0_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/theworld09.com\/&quot;&gt;TheWorld\u2800&lt;\/a&gt;",
"text": "RT @Orz619: \u307b\u3093\u304d\u3067\u30b9\u30d1\u30d6\u30ed\u3057\u3088\u3046\u304b\u3068\u691c\u8a0e\u4e2dw"
},
{
"created_at": "Mon, 20 May 2013 10:46:41 +0000",
"from_user": "Gatling_gun_k",
"from_user_id": 1126180920,
"from_user_id_str": "1126180920",
"from_user_name": "\uac1c\ud2c0\ub9c1 \uae30\uad00\ucd1d",
"geo": null,
"id": 336432787248787456,
"id_str": "336432787248787456",
"iso_language_code": "ko",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"source": "&lt;a href=&quot;http:\/\/twittbot.net\/&quot;&gt;twittbot.net&lt;\/a&gt;",
"text": "\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0\ud0c0!!"
},
{
"created_at": "Mon, 20 May 2013 10:22:40 +0000",
"from_user": "slam_gatling",
"from_user_id": 1316243516,
"from_user_id_str": "1316243516",
"from_user_name": "SxOxE",
"geo": null,
"id": 336426741893578754,
"id_str": "336426741893578754",
"iso_language_code": "ja",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3606289395\/106dee12ccd2fb0bca99ba4b85304d54_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3606289395\/106dee12ccd2fb0bca99ba4b85304d54_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
"text": "\u59b9\u304cHUNTER\u00d7HUNTER\u3092\u8aad\u3093\u3067\u308b\u305b\u3044\u304b\u3001\u4ffa\u3082\u4e2d\u5b66\u4ee5\u6765\u4e45\u3005\u306b\u30cf\u30de\u3063\u305f\u3002\u6697\u9ed2\u5927\u9678\u7de8\u304c\u3069\u3046\u306a\u308b\u304b\u6c17\u306b\u306a\u308b\u3051\u3069\u3001\u5927\u66ae\u7dad\u4eba\u307f\u305f\u3044\u306b\u8a71\u3092\u30c7\u30ab\u304f\u3057\u3059\u304e\u3066\u53ce\u96c6\u3064\u304b\u306a\u304f\u306a\u308b\u53ef\u80fd\u6027\u3082\u5fae\u30ec\u5b58\u3002\u3042\u3068\u30af\u30e9\u30d4\u30ab\u304c\u4eca\u5f8c\u3069\u3046\u95a2\u308f\u3063\u3066\u304f\u308b\u306e\u304b\u3082\u6c17\u306b\u306a\u308b\u3068\u3053\u308d\u3002"
},
{
"created_at": "Mon, 20 May 2013 09:46:45 +0000",
"from_user": "Gatling_gun_k",
"from_user_id": 1126180920,
"from_user_id_str": "1126180920",
"from_user_name": "\uac1c\ud2c0\ub9c1 \uae30\uad00\ucd1d",
"geo": null,
"id": 336417701356507136,
"id_str": "336417701356507136",
"iso_language_code": "ko",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"source": "&lt;a href=&quot;http:\/\/twittbot.net\/&quot;&gt;twittbot.net&lt;\/a&gt;",
"text": "\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c\ud22c!!"
},
{
"created_at": "Mon, 20 May 2013 09:17:47 +0000",
"from_user": "Gatling_gun_k",
"from_user_id": 1126180920,
"from_user_id_str": "1126180920",
"from_user_name": "\uac1c\ud2c0\ub9c1 \uae30\uad00\ucd1d",
"geo": null,
"id": 336410413707169792,
"id_str": "336410413707169792",
"iso_language_code": "ko",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3171674022\/d318e014542845396c11662986b4285d_normal.png",
"source": "&lt;a href=&quot;http:\/\/twittbot.net\/&quot;&gt;twittbot.net&lt;\/a&gt;",
"text": "\ub69c\ub450\ub450\ub450\ub457\ub450\ub450\ub450\ub450\ub450\ub450\ub450\ub450\ub450\ub450!!"
},
{
"created_at": "Mon, 20 May 2013 09:03:00 +0000",
"from_user": "Rebelzonderrede",
"from_user_id": 983435376,
"from_user_id_str": "983435376",
"from_user_name": "Rebel South",
"geo": null,
"id": 336406693384708096,
"id_str": "336406693384708096",
"iso_language_code": "nl",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2920503711\/6db32e22de8ee8efa92ba1e16ef341b6_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2920503711\/6db32e22de8ee8efa92ba1e16ef341b6_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/www.tweetdeck.com&quot;&gt;TweetDeck&lt;\/a&gt;",
"text": "20-5-1874: Sterfdag Alexander B. Dyer, Gen vd Unie. 1e Generaal die aanschaf Gatling gun nastreefde #amerikaanseburgeroorlog"
},
{
"created_at": "Mon, 20 May 2013 08:45:00 +0000",
"from_user": "MahdayMayday",
"from_user_id": 896598301,
"from_user_id_str": "896598301",
"from_user_name": "C H E ' N G A P !",
"geo": null,
"id": 336402162995310592,
"id_str": "336402162995310592",
"iso_language_code": "in",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/3089084467\/b5406e2a17e115108d798220ef872e59_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/3089084467\/b5406e2a17e115108d798220ef872e59_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
"text": "RT @mnhfz92: @MahdayMayday ah ye..bg Gomu Gomu no Elephant Gatling kang",
"in_reply_to_status_id": 336401088506900480,
"in_reply_to_status_id_str": "336401088506900480"
},
{
"created_at": "Mon, 20 May 2013 08:43:55 +0000",
"from_user": "mnhfz92",
"from_user_id": 282901250,
"from_user_id_str": "282901250",
"from_user_name": "Nor Hafiz",
"geo": null,
"id": 336401891959402496,
"id_str": "336401891959402496",
"iso_language_code": "in",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2661900827\/f41fc3f51c58daac67f1aa481de43819_normal.jpeg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2661900827\/f41fc3f51c58daac67f1aa481de43819_normal.jpeg",
"source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
"text": "@MahdayMayday ah ye..bg Gomu Gomu no Elephant Gatling kang",
"to_user": "MahdayMayday",
"to_user_id": 896598301,
"to_user_id_str": "896598301",
"to_user_name": "C H E ' N G A P !",
"in_reply_to_status_id": 336401088506900480,
"in_reply_to_status_id_str": "336401088506900480"
},
{
"created_at": "Mon, 20 May 2013 08:00:00 +0000",
"from_user": "origichara_bot",
"from_user_id": 410573195,
"from_user_id_str": "410573195",
"from_user_name": "\u307f\u3093\u306a\u306e\u30aa\u30ea\u30ad\u30e3\u30e9\u7d39\u4ecbbot",
"geo": null,
"id": 336390837846020096,
"id_str": "336390837846020096",
"iso_language_code": "ja",
"metadata": {
"result_type": "recent"
},
"profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/1634960810\/_____bot_normal.jpg",
"profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/1634960810\/_____bot_normal.jpg",
"source": "&lt;a href=&quot;http:\/\/twittbot.net\/&quot;&gt;twittbot.net&lt;\/a&gt;",
"text": "\u300c\u6551\u4e16\u4e3b(\u30e1\u30b7\u30a2)\u3068\u3088\u3079\u3001\u3044\u3044\u306a\uff1f\u300d\u300c\u9ed9\u308c\u5909\u614b\u5909\u4eba\u30b1\u30df\u30ab\u30eb\u30d6\u30ec\u30a4\u30f3\u5973\u304c\u3002\u79c1\u3060\u3063\u3066\u5143\u306f\u4eba\u9593\u3060\u300d\uff0f\u516b\u30f6\u5cf0\u81e8\u592a\u90ce\uff08\u7537\uff6515\u6b73\u30fb\u81ea\u79f0\u6551\u4e16\u4e3b\u306e\u4e2d\u4e8c\u75c5\u30cf\u30a4\u30ab\u30e9\u5c11\u5e74\uff09http:\/\/t.co\/FS7av2d077"
}
], "results_per_page": 15, "since_id": 0, "since_id_str": "0"}

100
json-path-web-test/src/main/resources/json/webxml.json

@ -0,0 +1,100 @@
{"web-app": {
"servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm@pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"cachePackageTagsTrack": 200,
"cachePackageTagsStore": 200,
"cachePackageTagsRefresh": 60,
"cacheTemplatesTrack": 100,
"cacheTemplatesStore": 50,
"cacheTemplatesRefresh": 15,
"cachePagesTrack": 200,
"cachePagesStore": 100,
"cachePagesRefresh": 10,
"cachePagesDirtyRead": 10,
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "debug",
"maxUrlLength": 500
}
},
{
"servlet-name": "cofaxEmail",
"servlet-class": "org.cofax.cds.EmailServlet",
"init-param": {
"mailHost": "mail1",
"mailHostOverride": "mail2"
}
},
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"
},
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"
},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true
}
}
],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"
},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"
}
}}

2
json-path-web-test/src/main/resources/simplelogger.properties

@ -0,0 +1,2 @@
org.slf4j.simpleLogger.defaultLogLevel=warn
org.slf4j.simpleLogger.log.com.jayway=debug

118
json-path-web-test/src/main/resources/templates/index.mustache

@ -0,0 +1,118 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JsonPath</title>
<link rel="stylesheet" href="/static/css/bootstrap.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="/static/js/jsonpath-0.8.0.js"></script>
<script type="text/javascript" src="/static/js/bootstrap.js"></script>
<script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
</head>
<body role="document">
<div class="container">
<div class="jumbotron">
<h3>JSONPath evaluator</h3>
</div>
<div class="row">
<div class="col-md-6">
<form method="post">
<div class="form-group">
<select id="templates" name="template" class="form-control" onChange='window.location="?template=" + this.value;'>
{{#templates}}
<option value="{{value}}" {{selected}}>{{name}}</option>
{{/templates}}
</select>
</div>
<div class="form-group">
<textarea id="json" name="json" rows="20" class="form-control">{{json}}</textarea>
</div>
<div class="radio">
<label>
<input type="radio" name="type" id="optTypeValue" value="value" {{value-checked}} />
Matching values
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="type" id="optTypePath" value="path" {{path-checked}} />
Normalized path expressions
</label>
</div>
<div class="input-group">
<input id="path" name="path" value="{{path}}" placeholder="Enter path" class="form-control"/>
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Go!</button>
</span>
</div>
</form>
</div>
<div class="col-md-6">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
<li class="active"><a href="#jayway" data-toggle="tab">Jayway</a></li>
<li><a href="#boon" data-toggle="tab">Boon</a></li>
<li><a href="#nebhale" data-toggle="tab">Nebhale</a></li>
<li><a href="#goessner" data-toggle="tab">Gossner</a></li>
</ul>
<div id="my-tab-content" class="tab-content">
{{#results}}
<div class="tab-pane {{active}}" id="{{provider}}">
<br/>
<span id="{{provider}}-time">{{time}}</span>&nbsp;millis
<hr/>
{{^error}}
<div class="row">
<div class="col-md-12">
<pre class="prettyprint" style="background-color: transparent; border: none;">{{result}}</pre>
</div>
</div>
{{/error}}
{{#error}}
<p class="bg-danger">{{error}}</p>
{{/error}}
</div>
{{/results}}
<div class="tab-pane" id="goessner">
<br/>
<span id="goessner-time"></span>&nbsp;millis
<hr/>
<div class="row">
<div class="col-md-12">
<pre id="goessner-res" class="prettyprint" style="background-color: transparent; border: none;"></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
$( document ).ready(function() {
if( $('#jayway').length )
{
//var value = $("#optTypeValue").prop("checked", true);
var value = $("#optTypeValue").is(':checked');
var start = new Date().getTime();
var json = JSON.parse($('#json').val());
var path = $('#path').val();
var res = '';
if(value){
res = jsonPath(json, path, {resultType:"VALUE"});
} else {
res = jsonPath(json, path, {resultType:"PATH"});
}
var elapsed = new Date().getTime() - start;
$("#goessner-time").html(elapsed);
$("#goessner-res").text(JSON.stringify(res, null, ' '));
}
});
</script>
</html>

10
json-path/src/main/java/com/jayway/jsonpath/Configuration.java

@ -14,15 +14,15 @@
*/
package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import static com.jayway.jsonpath.internal.Utils.*;
import static com.jayway.jsonpath.internal.Utils.notNull;
/**
* User: kalle
@ -33,13 +33,13 @@ public class Configuration {
private final JsonProvider provider;
private final EnumSet<Option> options;
private final Set<Option> options;
private Configuration(JsonProvider provider, EnumSet<Option> options) {
notNull(provider, "provider can not be null");
notNull(options, "options can not be null");
this.provider = provider;
this.options = options;
this.options = Collections.unmodifiableSet(options);
}
public Configuration provider(JsonProvider provider) {

143
json-path/src/main/java/com/jayway/jsonpath/Criteria.java

@ -14,13 +14,16 @@
*/
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.spi.compiler.PathCompiler;
import com.jayway.jsonpath.spi.compiler.Path;
import com.jayway.jsonpath.internal.Utils;
import java.util.*;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.Utils.isNumeric;
import static com.jayway.jsonpath.internal.Utils.notNull;
import static java.util.Arrays.asList;
import static com.jayway.jsonpath.internal.Utils.*;
/**
* @author Kalle Stenflo
@ -50,7 +53,9 @@ public class Criteria {
*/
private static final Object NOT_SET = new Object();
private final JsonPath key;
//private final JsonPath key;
//private final Path key;
private final Path key;
private final List<Criteria> criteriaChain;
@ -63,17 +68,29 @@ public class Criteria {
Utils.notEmpty(key, "key can not be null or empty");
this.criteriaChain = new ArrayList<Criteria>();
this.criteriaChain.add(this);
this.key = JsonPath.compile(key);
this.key = PathCompiler.tokenize(key);
}
private Criteria(Path path) {
Utils.notNull(path, "path can not be null");
this.criteriaChain = new ArrayList<Criteria>();
this.criteriaChain.add(this);
this.key = path;
}
private Criteria(List<Criteria> criteriaChain, String key) {
Utils.notEmpty(key, "key can not be null or empty");
this.criteriaChain = criteriaChain;
//this.key = JsonPath.compile(key);
this.criteriaChain.add(this);
this.key = JsonPath.compile(key);
//this.key = PathCompiler.compile(key);
this.key = PathCompiler.tokenize(key);
}
JsonPath getKey() {
//JsonPath getKey() {
//Path getKey() {
Path getKey() {
return this.key;
}
@ -83,11 +100,7 @@ public class Criteria {
* @param map map to check
* @return true if criteria is a match
*/
boolean matches(Map<String, Object> map, Configuration configuration) {
if (this.criteriaChain.size() == 1) {
return criteriaChain.get(0).singleObjectApply(map, configuration);
} else {
boolean matches(Object map, Configuration configuration) {
for (Criteria c : this.criteriaChain) {
if (!c.singleObjectApply(map, configuration)) {
return false;
@ -95,11 +108,14 @@ public class Criteria {
}
return true;
}
}
private static Object readSafely(JsonPath path, Map<String, Object> map) {
//private static Object readSafely(JsonPath path, Map<String, Object> map) {
//private static Object readSafely(Path path, Object map) {
private static Object readSafely(Path path, Object map) {
try {
return path.read(map);
return path.evaluate(map, Configuration.defaultConfiguration()).get();
//return PathEvaluator.evaluate(path, map, JsonProviderFactory.createProvider(), Collections.EMPTY_SET).getResult();
//return path. read(map);
} catch (InvalidPathException e) {
return null;
}
@ -119,7 +135,7 @@ public class Criteria {
return predicate.accept((T) singleObjectOrCollection);
}
boolean singleObjectApply(Map<String, Object> map, final Configuration configuration) {
private boolean singleObjectApply(Object map, final Configuration configuration) {
for (CriteriaType key : this.criteria.keySet()) {
@ -243,7 +259,9 @@ public class Criteria {
return !empty;
} else if (CriteriaType.EXISTS.equals(key)) {
if (configuration.getProvider().isArray(map)) {
return false;
}
final boolean exp = (Boolean) expectedVal;
return objectOrAnyCollectionItemMatches(map, new Predicate<Object>() {
@Override
@ -251,10 +269,17 @@ public class Criteria {
boolean act = true;
Object res;
try {
res = getKey().read(value, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
Set<Option> options = new HashSet<Option>() {{
add(Option.THROW_ON_MISSING_PROPERTY);
}};
//res = getKey().read(value, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
//res = PathEvaluator.evaluate(getKey(), value, configuration.getProvider(), options).getResult();
res = getKey().evaluate(value, Configuration.defaultConfiguration().options(Option.THROW_ON_MISSING_PROPERTY)).get();
if (configuration.getProvider().isArray(res)) {
if(getKey().isPathDefinite()){
//if(getKey().isDefinite()){
//if(getKey().isDefinite()){
if (getKey().isDefinite()) {
act = true;
} else {
act = (configuration.getProvider().length(res) > 0);
@ -331,6 +356,15 @@ public class Criteria {
return true;
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key filed name
* @return the new criteria
*/
public static Criteria where(Path key) {
return new Criteria(key);
}
/**
* Static factory method to create a Criteria using the provided key
@ -492,7 +526,8 @@ public class Criteria {
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value in the specified array all values in the array must be matched.
* The <code>all</code> operator is similar to $in, but instead of matching any value
* in the specified array all values in the array must be matched.
*
* @param o
* @return
@ -502,7 +537,8 @@ public class Criteria {
}
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value in the specified array all values in the array must be matched.
* The <code>all</code> operator is similar to $in, but instead of matching any value
* in the specified array all values in the array must be matched.
*
* @param c
* @return
@ -515,14 +551,19 @@ public class Criteria {
}
/**
* The <code>size</code> operator matches any array with the specified number of elements.
* The <code>size</code> operator matches:
*
* @param s
* <ol>
* <li>array with the specified number of elements.</li>
* <li>string with given length.</li>
* </ol>
*
* @param size
* @return
*/
public Criteria size(int s) {
public Criteria size(int size) {
checkFilterCanBeApplied(CriteriaType.SIZE);
criteria.put(CriteriaType.SIZE, s);
criteria.put(CriteriaType.SIZE, size);
return this;
}
@ -573,6 +614,45 @@ public class Criteria {
return this;
}
public Criteria matches(String operator, String expected) {
Object check;
if (expected.startsWith("'") && expected.endsWith("'")) {
check = expected.substring(1, expected.length() - 1);
} else if ("true".equals(expected)) {
check = Boolean.TRUE;
} else if ("false".equals(expected)) {
check = Boolean.FALSE;
} else if ("null".equals(expected)) {
check = null;
} else if (isNumeric(expected)) {
if (expected.contains(".")) {
check = Double.parseDouble(expected);
} else {
check = Integer.parseInt(expected);
}
} else {
throw new UnsupportedOperationException("Type not supported: " + expected);
}
if ("==".equals(operator)) {
return is(check);
} else if (">".equals(operator)) {
return gt(check);
} else if (">=".equals(operator)) {
return gte(check);
} else if ("<".equals(operator)) {
return lt(check);
} else if ("<=".equals(operator)) {
return lte(check);
} else if ("!=".equals(operator)) {
return ne(check);
} else if ("<>".equals(operator)) {
return ne(check);
} else {
throw new UnsupportedOperationException("Operator not supported: " + operator);
}
}
/**
* Creates an 'or' criteria using the $or operator for all of the provided criteria
@ -608,7 +688,9 @@ public class Criteria {
}
private void checkFilterCanBeApplied(CriteriaType type) {
if (getKey().getTokenizer().size() > 2) {
//if (getKey().getTokenizer().size() > 2) {
//if(getKey().getComponents().length > 2) {
if (getKey().tokenCount() > 2) {
throw new IllegalArgumentException("Cannot use " + type + " filter on a multi-level path expression");
}
}
@ -618,4 +700,17 @@ public class Criteria {
boolean accept(T value);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Iterator<Criteria> iterator = criteriaChain.iterator();
Criteria c = iterator.next();
if (c.isValue != NOT_SET) {
sb.append("@").append(key.toString().substring(1) + " == " + ((c.isValue instanceof String) ? ("'" + c.isValue + "'") : c.isValue.toString()));
}
return sb.toString();
}
}

618
json-path/src/main/java/com/jayway/jsonpath/Criteria2.java

@ -0,0 +1,618 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.spi.compiler.PathCompiler;
import com.jayway.jsonpath.spi.compiler.EvaluationContext;
import com.jayway.jsonpath.spi.compiler.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.Utils.join;
import static com.jayway.jsonpath.internal.Utils.notNull;
/**
*
*/
public class Criteria2 implements Predicate {
private static final Logger logger = LoggerFactory.getLogger(Criteria2.class);
private final Path path;
private CriteriaType criteriaType;
private Object expected;
private final List<Criteria2> criteriaChain;
private enum CriteriaType {
EQ {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = (0 == safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
NE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = (0 != safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
GT {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 > safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
GTE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 >= safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
LT {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 < safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
LTE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 <= safeCompare(expected, actual, configuration));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
},
IN {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = false;
Collection exps = (Collection) expected;
for (Object exp : exps) {
if (0 == safeCompare(exp, actual, configuration)) {
res = true;
break;
}
}
logger.debug("[{}] {} [{}] => {}", actual, name(), join(", ", exps), res);
return res;
}
},
NIN {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
Collection nexps = (Collection) expected;
boolean res = !nexps.contains(actual);
logger.debug("[{}] {} [{}] => {}", actual, name(), join(", ", nexps), res);
return res;
}
},
ALL {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = true;
Collection exps = (Collection) expected;
if (configuration.getProvider().isArray(actual)) {
for (Object exp : exps) {
boolean found = false;
for (Object check : configuration.getProvider().toIterable(actual)) {
if (0 == safeCompare(exp, check, configuration)) {
found = true;
break;
}
}
if (!found) {
res = false;
break;
}
}
logger.debug("[{}] {} [{}] => {}", join(", ", configuration.getProvider().toIterable(actual)), name(), join(", ", exps), res);
} else {
res = false;
logger.debug("[{}] {} [{}] => {}", "<NOT AN ARRAY>", name(), join(", ", exps), res);
}
return res;
}
},
SIZE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
int size = (Integer) expected;
boolean res;
if (configuration.getProvider().isArray(actual)) {
int length = configuration.getProvider().length(actual);
res = length == size;
logger.debug("Array with size {} {} {} => {}", length, name(), size, res);
} else if (actual instanceof String) {
int length = ((String) actual).length();
res = length == size;
logger.debug("String with length {} {} {} => {}", length, name(), size, res);
} else {
res = false;
logger.debug("{} {} {} => {}", actual == null ? "null" : actual.getClass().getName(), name(), size, res);
}
return res;
}
},
EXISTS {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
//This must be handled outside
throw new UnsupportedOperationException();
}
},
TYPE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
final Class<?> expType = (Class<?>) expected;
final Class<?> actType = actual == null ? null : actual.getClass();
if (actType != null) {
return expType.isAssignableFrom(actType);
}
return false;
}
},
REGEX {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = false;
final Pattern pattern = (Pattern) expected;
if (actual != null && actual instanceof String) {
res = pattern.matcher(actual.toString()).matches();
}
logger.debug("[{}] {} [{}] => {}", actual, name(), expected.toString(), res);
return res;
}
},
MATCHES {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
Predicate exp = (Predicate) expected;
return exp.apply(actual, configuration);
}
},
NOT_EMPTY {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = false;
if (actual != null) {
if (configuration.getProvider().isArray(actual)) {
int len = configuration.getProvider().length(actual);
res = (0 != len);
logger.debug("array length = {} {} => {}", len, name(), res);
} else if (actual instanceof String) {
int len = ((String) actual).length();
res = (0 != len);
logger.debug("string length = {} {} => {}", len, name(), res);
}
}
return res;
}
};
abstract boolean eval(Object expected, Object actual, Configuration configuration);
public static CriteriaType parse(String str) {
if ("==".equals(str)) {
return EQ;
} else if (">".equals(str)) {
return GT;
} else if (">=".equals(str)) {
return GTE;
} else if ("<".equals(str)) {
return LT;
} else if ("<=".equals(str)) {
return LTE;
} else if ("!=".equals(str)) {
return NE;
} else {
throw new UnsupportedOperationException("CriteriaType " + str + " can not be parsed");
}
}
}
private Criteria2(List<Criteria2> criteriaChain, Path path) {
if (!path.isDefinite()) {
throw new InvalidCriteriaException("A criteria path must be definite. The path " + path.toString() + " is not!");
}
this.path = path;
this.criteriaChain = criteriaChain;
this.criteriaChain.add(this);
}
private Criteria2(Path path) {
this(new LinkedList<Criteria2>(), path);
}
private Criteria2(Path path, CriteriaType criteriaType, Object expected) {
this(new LinkedList<Criteria2>(), path);
this.criteriaType = criteriaType;
this.expected = expected;
}
@Override
public boolean apply(Object model, Configuration configuration) {
for (Criteria2 criteria : criteriaChain) {
if (!criteria.eval(model, configuration)) {
return false;
}
}
return true;
}
private boolean eval(Object model, Configuration configuration) {
if (CriteriaType.EXISTS == criteriaType) {
boolean exists = ((Boolean) expected);
try {
path.evaluate(model, configuration.options(Option.THROW_ON_MISSING_PROPERTY)).get();
return exists == true;
} catch (PathNotFoundException e) {
return exists == false;
}
} else {
try {
final Object actual = path.evaluate(model, configuration).get();
return criteriaType.eval(expected, actual, configuration);
} catch (CompareException e) {
return false;
} catch (PathNotFoundException e) {
return false;
}
}
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key filed name
* @return the new criteria
*/
public static Criteria2 where(Path key) {
return new Criteria2(key);
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key filed name
* @return the new criteria
*/
public static Criteria2 where(String key) {
return where(PathCompiler.tokenize(key));
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key ads new filed to criteria
* @return the criteria builder
*/
public Criteria2 and(String key) {
return new Criteria2(this.criteriaChain, PathCompiler.tokenize(key));
}
/**
* Creates a criterion using equality
*
* @param o
* @return
*/
public Criteria2 is(Object o) {
this.criteriaType = CriteriaType.TYPE.EQ;
this.expected = o;
return this;
}
/**
* Creates a criterion using equality
*
* @param o
* @return
*/
public Criteria2 eq(Object o) {
return is(o);
}
/**
* Creates a criterion using the <b>!=</b> operator
*
* @param o
* @return
*/
public Criteria2 ne(Object o) {
this.criteriaType = CriteriaType.TYPE.NE;
this.expected = o;
return this;
}
/**
* Creates a criterion using the <b>&lt;</b> operator
*
* @param o
* @return
*/
public Criteria2 lt(Object o) {
this.criteriaType = CriteriaType.TYPE.LT;
this.expected = o;
return this;
}
/**
* Creates a criterion using the <b>&lt;=</b> operator
*
* @param o
* @return
*/
public Criteria2 lte(Object o) {
this.criteriaType = CriteriaType.TYPE.LTE;
this.expected = o;
return this;
}
/**
* Creates a criterion using the <b>&gt;</b> operator
*
* @param o
* @return
*/
public Criteria2 gt(Object o) {
this.criteriaType = CriteriaType.TYPE.GT;
this.expected = o;
return this;
}
/**
* Creates a criterion using the <b>&gt;=</b> operator
*
* @param o
* @return
*/
public Criteria2 gte(Object o) {
this.criteriaType = CriteriaType.TYPE.GTE;
this.expected = o;
return this;
}
/**
* Creates a criterion using a Regex
*
* @param pattern
* @return
*/
public Criteria2 regex(Pattern pattern) {
notNull(pattern, "pattern can not be null");
this.criteriaType = CriteriaType.TYPE.REGEX;
this.expected = pattern;
return this;
}
/**
* The <code>in</code> operator is analogous to the SQL IN modifier, allowing you
* to specify an array of possible matches.
*
* @param o the values to match against
* @return
*/
public Criteria2 in(Object... o) {
return in(Arrays.asList(o));
}
/**
* The <code>in</code> operator is analogous to the SQL IN modifier, allowing you
* to specify an array of possible matches.
*
* @param c the collection containing the values to match against
* @return
*/
public Criteria2 in(Collection<?> c) {
notNull(c, "collection can not be null");
this.criteriaType = CriteriaType.TYPE.IN;
this.expected = c;
return this;
}
/**
* The <code>nin</code> operator is similar to $in except that it selects objects for
* which the specified field does not have any value in the specified array.
*
* @param o the values to match against
* @return
*/
public Criteria2 nin(Object... o) {
return nin(Arrays.asList(o));
}
/**
* The <code>nin</code> operator is similar to $in except that it selects objects for
* which the specified field does not have any value in the specified array.
*
* @param c the values to match against
* @return
*/
public Criteria2 nin(Collection<?> c) {
notNull(c, "collection can not be null");
this.criteriaType = CriteriaType.TYPE.NIN;
this.expected = c;
return this;
}
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value
* in the specified array all values in the array must be matched.
*
* @param o
* @return
*/
public Criteria2 all(Object... o) {
return all(Arrays.asList(o));
}
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value
* in the specified array all values in the array must be matched.
*
* @param c
* @return
*/
public Criteria2 all(Collection<?> c) {
notNull(c, "collection can not be null");
this.criteriaType = CriteriaType.TYPE.ALL;
this.expected = c;
return this;
}
/**
* The <code>size</code> operator matches:
* <p/>
* <ol>
* <li>array with the specified number of elements.</li>
* <li>string with given length.</li>
* </ol>
*
* @param size
* @return
*/
public Criteria2 size(int size) {
this.criteriaType = CriteriaType.TYPE.SIZE;
this.expected = size;
return this;
}
/**
* Check for existence (or lack thereof) of a field.
*
* @param b
* @return
*/
public Criteria2 exists(boolean b) {
this.criteriaType = CriteriaType.TYPE.EXISTS;
this.expected = b;
return this;
}
/**
* The $type operator matches values based on their Java type.
*
* @param t
* @return
*/
public Criteria2 type(Class<?> t) {
notNull(t, "type can not be null");
this.criteriaType = CriteriaType.TYPE.TYPE;
this.expected = t;
return this;
}
/**
* The <code>notEmpty</code> operator checks that an array or String is not empty.
*
* @return
*/
public Criteria2 notEmpty() {
this.criteriaType = CriteriaType.TYPE.NOT_EMPTY;
this.expected = null;
return this;
}
/**
* The <code>matches</code> operator checks that an object matches the given predicate.
*
* @return
*/
public Criteria2 matches(Predicate p) {
this.criteriaType = CriteriaType.TYPE.MATCHES;
this.expected = p;
return this;
}
private static int safeCompare(Object expected, Object actual, Configuration configuration) {
if (expected == null && actual != null) {
return -1;
} else if (expected != null && actual == null) {
return 1;
} else if (expected == null && actual == null) {
return 0;
} else if (expected instanceof String && actual instanceof String) {
return ((String) expected).compareTo((String) actual);
} else if (expected instanceof Number && actual instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(actual.toString()));
} else if (expected instanceof String && actual instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(actual.toString()));
} else if (expected instanceof String && actual instanceof Boolean) {
Boolean e = Boolean.valueOf((String)expected);
Boolean a = (Boolean) actual;
return e.compareTo(a);
} else if (expected instanceof Boolean && actual instanceof Boolean) {
Boolean e = (Boolean) expected;
Boolean a = (Boolean) actual;
return e.compareTo(a);
} else {
logger.debug("Can not compare a {} with a {}", expected.getClass().getName(), actual.getClass().getName());
throw new CompareException();
}
}
private static class CompareException extends RuntimeException {
}
public static Criteria2 create(String path, String operator, String expected) {
if (expected.startsWith("'") && expected.endsWith("'")) {
expected = expected.substring(1, expected.length() - 1);
}
Path p = PathCompiler.tokenize(path);
if (operator.isEmpty()) {
return Criteria2.where(path).exists(true);
} else {
return new Criteria2(p, CriteriaType.parse(operator), expected);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(path.toString())
.append("|")
.append(criteriaType.name())
.append("|")
.append(expected)
.append("|");
return sb.toString();
}
}

48
json-path/src/main/java/com/jayway/jsonpath/Filter.java

@ -14,31 +14,31 @@
*/
package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A filter is used to filter the content of a JSON array in a JSONPath.
*
* <p/>
* Sample
*
* <p/>
* <code>
* String doc = {"items": [{"name" : "john"}, {"name": "bob"}]}
*
* <p/>
* List<String> names = JsonPath.read(doc, "$items[?].name", Filter.filter(Criteria.where("name").is("john"));
* </code>
*
* @see Criteria
*
* @author Kalle Stenflo
* @see Criteria
*/
public abstract class Filter<T> {
/**
* Creates a new filter based on given criteria
*
* @param criteria the filter criteria
* @return a new filter
*/
@ -48,6 +48,7 @@ public abstract class Filter<T> {
/**
* Filters the provided list based on this filter configuration
*
* @param filterItems items to filter
* @param configuration the json provider configuration that is used to create the result list
* @return the filtered list
@ -65,6 +66,7 @@ public abstract class Filter<T> {
/**
* Check if this filter will accept or reject the given object
*
* @param obj item to check
* @return true if filter matches
*/
@ -72,6 +74,7 @@ public abstract class Filter<T> {
/**
* Check if this filter will accept or reject the given object
*
* @param obj item to check
* @param configuration
* @return true if filter matches
@ -104,14 +107,15 @@ public abstract class Filter<T> {
return accept(obj);
}
@Override
public Filter addCriteria(Criteria criteria) {
throw new UnsupportedOperationException("can not add criteria to a FilterAdapter.");
}
}
}
private static class MapFilter extends FilterAdapter<Map<String, Object>> {
private static class MapFilter extends FilterAdapter<Object> {
private HashMap<String, Criteria> criteria = new LinkedHashMap<String, Criteria>();
@ -120,8 +124,8 @@ public abstract class Filter<T> {
}
public MapFilter addCriteria(Criteria criteria) {
Criteria existing = this.criteria.get(criteria.getKey().getPath());
String key = criteria.getKey().getPath();
String key = criteria.getKey().toString();
Criteria existing = this.criteria.get(key);
if (existing == null) {
this.criteria.put(key, criteria);
} else {
@ -131,12 +135,12 @@ public abstract class Filter<T> {
}
@Override
public boolean accept(Map<String, Object> map) {
public boolean accept(Object map) {
return accept(map, Configuration.defaultConfiguration());
}
@Override
public boolean accept(Map<String, Object> map, Configuration configuration) {
public boolean accept(Object map, Configuration configuration) {
for (Criteria criterion : this.criteria.values()) {
if (!criterion.matches(map, configuration)) {
return false;
@ -144,5 +148,23 @@ public abstract class Filter<T> {
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[?(");
Iterator<Criteria> criteriaIterator = criteria.values().iterator();
Criteria criterion = criteriaIterator.next();
sb.append(criterion.toString());
while (criteriaIterator.hasNext()) {
sb.append(" && ")
.append(criteriaIterator.next().toString());
}
sb.append(")]");
return sb.toString();
}
}
}

54
json-path/src/main/java/com/jayway/jsonpath/Filter2.java

@ -0,0 +1,54 @@
package com.jayway.jsonpath;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
/**
*
*/
public class Filter2 implements Predicate {
private List<Criteria2> criteriaList = new ArrayList<Criteria2>();
private Filter2(Criteria2 criteria) {
this.criteriaList.add(criteria);
}
private Filter2(List<Criteria2> criteriaList) {
this.criteriaList = criteriaList;
}
public static Filter2 filter(Criteria2 criteria) {
return new Filter2(criteria);
}
public static Filter2 filter(List<Criteria2> criteriaList) {
return new Filter2(criteriaList);
}
@Override
public boolean apply(Object target, Configuration configuration) {
for (Criteria2 criteria : criteriaList) {
if (!criteria.apply(target, configuration)) {
return false;
}
}
return true;
}
public void addCriteria(Criteria2 criteria) {
criteriaList.add(criteria);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Criteria2 crit : criteriaList) {
sb.append(crit.toString());
}
return sb.toString();
}
}

27
json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java

@ -1,27 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath;
/**
* @author Kalle Stenflo
*/
@SuppressWarnings("serial")
public class IndefinitePathException extends RuntimeException {
public IndefinitePathException(String path) {
super("The path " + path + " is not definite");
}
}

1066
json-path/src/main/java/com/jayway/jsonpath/JsonModel.java

File diff suppressed because it is too large Load Diff

137
json-path/src/main/java/com/jayway/jsonpath/JsonPath.java

@ -15,27 +15,22 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.JsonReader;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.internal.PathTokenizer;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
import com.jayway.jsonpath.spi.HttpProviderFactory;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jayway.jsonpath.internal.*;
import com.jayway.jsonpath.internal.spi.compiler.PathCompiler;
import com.jayway.jsonpath.spi.http.HttpProviderFactory;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import com.jayway.jsonpath.spi.compiler.Path;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.Utils.*;
import static java.util.Arrays.asList;
/**
* <p/>
@ -100,54 +95,22 @@ import static java.util.Arrays.asList;
*/
public class JsonPath {
private static final Logger LOG = LoggerFactory.getLogger(JsonPath.class.getName());
private static final Pattern DEFINITE_PATH_PATTERN = Pattern.compile(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:\\s?]|\\[\\s?:|>|\\(|<|=|\\+).*");
private static Pattern DEFINITE_PATH_PATTERN = Pattern.compile(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:\\s?]|\\[\\s?:|>|\\(|<|=|\\+).*");
private PathTokenizer tokenizer;
private LinkedList<Filter> filters;
private JsonPath(String jsonPath, Filter[] filters) {
private final Path path;
private JsonPath(String jsonPath, Filter2[] filters) {
notNull(jsonPath, "path can not be null");
jsonPath = jsonPath.trim();
notEmpty(jsonPath, "path can not be empty");
int filterCountInPath = Utils.countMatches(jsonPath, "[?]");
isTrue(filterCountInPath == filters.length, "Filters in path ([?]) does not match provided filters.");
this.tokenizer = new PathTokenizer(jsonPath);
if(LOG.isDebugEnabled()){
LOG.debug("New JsonPath:\n{}", this.tokenizer.toString());
}
this.filters = new LinkedList<Filter>();
this.filters.addAll(asList(filters));
}
PathTokenizer getTokenizer() {
return this.tokenizer;
this.path = PathCompiler.tokenize(jsonPath, filters);
}
public JsonPath copy() {
Filter[] filterCopy = filters.isEmpty()?new Filter[0]:new Filter[filters.size()];
return new JsonPath(tokenizer.getPath(), filters.toArray(filterCopy));
}
/**
* Returns the string representation of this JsonPath
*
* @return path as String
*/
public String getPath() {
return this.tokenizer.getPath();
return this.path.toString();
}
/**
@ -172,7 +135,6 @@ public class JsonPath {
*/
public static boolean isPathDefinite(String path) {
String preparedPath = path.replaceAll("\"[^\"\\\\\\n\r]*\"", "");
return !DEFINITE_PATH_PATTERN.matcher(preparedPath).matches();
}
@ -198,7 +160,7 @@ public class JsonPath {
* @return true if path is definite (points to single item)
*/
public boolean isPathDefinite() {
return JsonPath.isPathDefinite(getPath());
return path.isDefinite();
}
/**
@ -208,7 +170,7 @@ public class JsonPath {
*
* @param jsonObject a container Object
* @param <T> expected return type
* @return list of objects matched by the given path
* @return object(s) matched by the given path
*/
@SuppressWarnings({"unchecked"})
public <T> T read(Object jsonObject) {
@ -223,46 +185,36 @@ public class JsonPath {
* @param jsonObject a container Object
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
* @return object(s) matched by the given path
*/
public <T> T read(Object jsonObject, Configuration configuration) {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
if (this.getPath().equals("$")) {
//This path only references the whole object. No need to do any work here...
return (T) jsonObject;
}
if (!configuration.getProvider().isContainer(jsonObject)) {
throw new IllegalArgumentException("Invalid container object");
return path.evaluate(jsonObject, configuration).get();
}
LinkedList<Filter> contextFilters = new LinkedList<Filter>(filters);
Object result = jsonObject;
boolean inArrayContext = false;
for (PathToken pathToken : tokenizer) {
PathTokenFilter filter = pathToken.getFilter();
if(LOG.isDebugEnabled()){
LOG.debug("Applying filter: " + filter + " to " + result);
}
result = filter.filter(result, configuration, contextFilters, inArrayContext);
if(result == null && !pathToken.isEndToken()){
throw new PathNotFoundException("Path token: '" + pathToken.getFragment() + "' not found.");
/**
* Applies this JsonPath to the provided json document.
* Note that the document must be identified as either a List or Map by
* the {@link JsonProvider}
*
* @param jsonObject a container Object
* @return list of definite path strings to object matched by path
*/
public List<String> readPathList(Object jsonObject) {
return readPathList(jsonObject, Configuration.defaultConfiguration());
}
if (!inArrayContext) {
inArrayContext = filter.isArrayFilter();
}
}
return (T) result;
/**
* Applies this JsonPath to the provided json document.
* Note that the document must be identified as either a List or Map by
* the {@link JsonProvider}
*
* @param jsonObject a container Object
* @param configuration configuration to use
* @return list of definite path strings to object matched by path
*/
public List<String> readPathList(Object jsonObject, Configuration configuration) {
return path.evaluate(jsonObject, configuration).getPathList();
}
/**
@ -420,7 +372,7 @@ public class JsonPath {
* @param filters filters to be applied to the filter place holders [?] in the path
* @return compiled JsonPath
*/
public static JsonPath compile(String jsonPath, Filter... filters) {
public static JsonPath compile(String jsonPath, Filter2... filters) {
notEmpty(jsonPath, "json can not be null or empty");
return new JsonPath(jsonPath, filters);
@ -443,8 +395,9 @@ public class JsonPath {
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(Object json, String jsonPath, Filter... filters) {
return compile(jsonPath, filters).read(json);
public static <T> T read(Object json, String jsonPath, Filter2... filters) {
//return compile(jsonPath, filters).read(json);
return new JsonReader().parse(json).read(jsonPath, filters);
}
@ -458,7 +411,7 @@ public class JsonPath {
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(String json, String jsonPath, Filter... filters) {
public static <T> T read(String json, String jsonPath, Filter2... filters) {
return new JsonReader().parse(json).read(jsonPath, filters);
}
@ -472,7 +425,7 @@ public class JsonPath {
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(URL jsonURL, String jsonPath, Filter... filters) throws IOException {
public static <T> T read(URL jsonURL, String jsonPath, Filter2... filters) throws IOException {
return new JsonReader().parse(jsonURL).read(jsonPath, filters);
}
@ -486,7 +439,7 @@ public class JsonPath {
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(File jsonFile, String jsonPath, Filter... filters) throws IOException {
public static <T> T read(File jsonFile, String jsonPath, Filter2... filters) throws IOException {
return new JsonReader().parse(jsonFile).read(jsonPath, filters);
}
@ -500,7 +453,7 @@ public class JsonPath {
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(InputStream jsonInputStream, String jsonPath, Filter... filters) throws IOException {
public static <T> T read(InputStream jsonInputStream, String jsonPath, Filter2... filters) throws IOException {
return new JsonReader().parse(jsonInputStream).read(jsonPath, filters);
}

4
json-path/src/main/java/com/jayway/jsonpath/ParseContext.java

@ -27,8 +27,12 @@ import java.net.URL;
public interface ParseContext {
ReadContext parse(String json);
ReadContext parse(Object json);
ReadContext parse(InputStream json);
ReadContext parse(File json) throws IOException;
ReadContext parse(URL json) throws IOException;
}

9
json-path/src/main/java/com/jayway/jsonpath/Predicate.java

@ -0,0 +1,9 @@
package com.jayway.jsonpath;
/**
*
*/
public interface Predicate {
boolean apply(Object target, Configuration configuration);
}

22
json-path/src/main/java/com/jayway/jsonpath/ReadContext.java

@ -14,6 +14,8 @@
*/
package com.jayway.jsonpath;
import java.util.List;
/**
* User: kalle
* Date: 8/30/13
@ -36,7 +38,7 @@ public interface ReadContext {
* @param <T>
* @return result
*/
<T> T read(String path, Filter... filters);
<T> T read(String path, Filter2... filters);
/**
* Reads the given path from this context
@ -46,4 +48,22 @@ public interface ReadContext {
* @return result
*/
<T> T read(JsonPath path);
/**
* Reads the given path list from this context
*
* @param path a container Object
* @param filters filters
* @return list of definite path strings to object matched by path
*/
List<String> readPathList(String path, Filter2... filters);
/**
* Reads the given path list from this context
*
* @param path path to apply
* @return list of definite path strings to object matched by path
*/
List<String> readPathList(JsonPath path);
}

2
json-path/src/main/java/com/jayway/jsonpath/Transformer.java

@ -20,7 +20,6 @@ package com.jayway.jsonpath;
public interface Transformer<T> {
/**
*
* @param obj object to transform
* @param configuration configuration to use
* @return the transformed object
@ -28,5 +27,4 @@ public interface Transformer<T> {
public Object transform(T obj, Configuration configuration);
}

101
json-path/src/main/java/com/jayway/jsonpath/internal/Cache.java

@ -0,0 +1,101 @@
package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.spi.compiler.Path;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
public class Cache {
private final ReentrantLock lock = new ReentrantLock();
private final Map<String, Path> map = new ConcurrentHashMap<String, Path>();
private final Deque<String> queue = new LinkedList<String>();
private final int limit;
public Cache(int limit) {
this.limit = limit;
}
public void put(String key, Path value) {
Path oldValue = map.put(key, value);
if (oldValue != null) {
removeThenAddKey(key);
} else {
addKey(key);
}
if (map.size() > limit) {
map.remove(removeLast());
}
}
public Path get(String key) {
removeThenAddKey(key);
return map.get(key);
}
private void addKey(String key) {
lock.lock();
try {
queue.addFirst(key);
} finally {
lock.unlock();
}
}
private String removeLast() {
lock.lock();
try {
final String removedKey = queue.removeLast();
return removedKey;
} finally {
lock.unlock();
}
}
private void removeThenAddKey(String key) {
lock.lock();
try {
queue.removeFirstOccurrence(key);
queue.addFirst(key);
} finally {
lock.unlock();
}
}
private void removeFirstOccurrence(String key) {
lock.lock();
try {
queue.removeFirstOccurrence(key);
} finally {
lock.unlock();
}
}
public Path getSilent(String key) {
return map.get(key);
}
public void remove(String key) {
removeFirstOccurrence(key);
map.remove(key);
}
public int size() {
return map.size();
}
public String toString() {
return map.toString();
}
}

51
json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java

@ -1,40 +1,49 @@
package com.jayway.jsonpath.internal;
public class JsonFormatter
{
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JsonFormatter {
private static final Logger logger = LoggerFactory.getLogger(JsonFormatter.class);
private static final String INDENT = " ";
private static final String NEW_LINE = System.getProperty("line.separator");
private static void appendIndent(StringBuilder sb, int count)
{
private static void appendIndent(StringBuilder sb, int count) {
for (; count > 0; --count) sb.append(INDENT);
}
private static boolean isEscaped(StringBuilder sb, int index)
{
private static boolean isEscaped(StringBuilder sb, int index) {
boolean escaped = false;
while (index > 0 && sb.charAt(--index) == '\\') escaped = !escaped;
int idx = Math.min(index, sb.length());
try {
while (idx > 0 && sb.charAt(--idx) == '\\') {
escaped = !escaped;
}
} catch (Exception e){
logger.warn("Failed to check escaped ", e);
}
return escaped;
}
public static String prettyPrint(String input)
{
public static String prettyPrint(String input) {
input = input.replaceAll("[\\r\\n]", "");
StringBuilder output = new StringBuilder(input.length() * 2);
boolean quoteOpened = false;
int depth = 0;
for(int i=0; i<input.length(); ++i)
{
for (int i = 0; i < input.length(); ++i) {
char ch = input.charAt(i);
switch (ch)
{
switch (ch) {
case '{':
case '[':
output.append(ch);
if (!quoteOpened)
{
if (!quoteOpened) {
output.append(NEW_LINE);
appendIndent(output, ++depth);
}
@ -43,8 +52,7 @@ public class JsonFormatter
case ']':
if (quoteOpened)
output.append(ch);
else
{
else {
output.append(NEW_LINE);
appendIndent(output, --depth);
output.append(ch);
@ -53,17 +61,14 @@ public class JsonFormatter
case '"':
case '\'':
output.append(ch);
if (quoteOpened)
{
if (quoteOpened) {
if (!isEscaped(output, i))
quoteOpened = false;
}
else quoteOpened = true;
} else quoteOpened = true;
break;
case ',':
output.append(ch);
if (!quoteOpened)
{
if (!quoteOpened) {
output.append(NEW_LINE);
appendIndent(output, depth);
}

24
json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java

@ -1,16 +1,17 @@
package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.*;
import com.jayway.jsonpath.spi.HttpProviderFactory;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.http.HttpProviderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import static com.jayway.jsonpath.internal.Utils.*;
import static com.jayway.jsonpath.internal.Utils.notEmpty;
import static com.jayway.jsonpath.internal.Utils.notNull;
/**
* User: kalle
@ -26,10 +27,6 @@ public class JsonReader implements ParseContext, ReadContext {
this(Configuration.defaultConfiguration());
}
public JsonReader(JsonProvider jsonProvider) {
this(Configuration.builder().jsonProvider(jsonProvider).build());
}
public JsonReader(Configuration configuration) {
notNull(configuration, "configuration can not be null");
this.configuration = configuration;
@ -92,7 +89,7 @@ public class JsonReader implements ParseContext, ReadContext {
}
@Override
public <T> T read(String path, Filter... filters) {
public <T> T read(String path, Filter2... filters) {
notEmpty(path, "path can not be null or empty");
return read(JsonPath.compile(path, filters));
}
@ -103,4 +100,15 @@ public class JsonReader implements ParseContext, ReadContext {
return path.read(json, configuration);
}
@Override
public List<String> readPathList(String path, Filter2... filters) {
notEmpty(path, "path can not be null or empty");
return readPathList(JsonPath.compile(path, filters));
}
@Override
public List<String> readPathList(JsonPath path) {
notNull(path, "path can not be null");
return path.readPathList(json, configuration);
}
}

159
json-path/src/main/java/com/jayway/jsonpath/internal/Parser.java

@ -0,0 +1,159 @@
package com.jayway.jsonpath.internal;
import java.util.Arrays;
public class Parser {
public enum Token {
DOT('.'),
OPEN_BRACKET('['),
CLOSE_BRACKET(']'),
OPEN_PARENTHESIS('('),
CLOSE_PARENTHESIS(')'),
BLANK(' '),
TICK('\''),
END('^');
private final char c;
Token(char c) {
this.c = c;
}
}
protected String buffer;
private int i;
public Parser(String src) {
buffer = src;
i = -1;
}
public char prev(){
return buffer.charAt(i-1);
}
public boolean prevIs(char c){
if(i <= 0){
return false;
}
return prev() == c;
}
public char curr(){
return buffer.charAt(i);
}
public char peek(){
return buffer.charAt(i + 1);
}
public boolean peekIs(Token token){
return buffer.charAt(i+1) == token.c;
}
public char next(){
return buffer.charAt(++i);
}
public boolean hasNext(){
return i < buffer.length() - 1;
}
public String next(int count){
//i++;
int y = i;
i = i + count - 1;
return buffer.substring(y, i+1);
//return Arrays.copyOfRange(buffer, y, i+1);
}
public void trim(Token token){
while (peekIs(token)){
next();
}
}
public int findOffset(Token... tokens){
int y = i;
char check;
do {
if(y == buffer.length()-1 && contains(tokens, Token.END.c)){
y++;
break;
}
check = buffer.charAt(++y);
} while (!contains(tokens, check));
return y-i;
}
public String nextUntil(Token... tokens){
next();
int offset = findOffset(tokens);
return next(offset);
}
public boolean isInts(String chars, boolean allowSequence){
for (int i = 0; i < chars.length(); i++){
char c = chars.charAt(i);
boolean isSequenceChar = (c == ' ' || c == ',');
if(!Character.isDigit(c) || (isSequenceChar && allowSequence)){
return false;
}
}
return true;
}
private boolean contains(Token[] arr, char checkFor){
for (int i = 0; i < arr.length; i++){
if(arr[i].c == checkFor){
return true;
}
}
return false;
}
/*
public Filter2 parse(String filterString){
char[] chars = filterString.trim().toCharArray();
int i = 0;
do {
char current = chars[i];
switch (current){
case '?':
break;
case '(':
break;
case ')':
break;
case '\'';
}
i++;
} while (i < chars.length);
}
*/
}

191
json-path/src/main/java/com/jayway/jsonpath/internal/PathFormalizer.java

@ -0,0 +1,191 @@
package com.jayway.jsonpath.internal;
import java.util.ArrayList;
import java.util.List;
public class PathFormalizer extends Parser {
private static final Fragment ROOT = new Fragment(Type.ROOT, "$");
private static final Fragment SCAN = new Fragment(Type.SCAN, "..");
StringBuilder formalized = new StringBuilder();
public PathFormalizer(String path) {
super(path);
}
//$.store.book[?(@.isbn)].isbn
//$['store']['book'][?(@['isbn'])]['isbn']
public String formalize() {
TokenBuffer buffer = new TokenBuffer();
do {
char current = next();
switch (current) {
case '$':
buffer.append("$").flush();
break;
case '.':
if (!buffer.isEmpty()) {
buffer.flush();
}
if (peekIs(Token.DOT)) {
next();
buffer.append("..").flush();
}
break;
case '[':
if (!buffer.isEmpty()) {
buffer.flush();
}
break;
case ']':
if (!buffer.isEmpty()) {
buffer.flush();
}
break;
case '?':
if (peekIs(Token.OPEN_PARENTHESIS)) {
buffer.append("?" + nextUntil(Token.CLOSE_BRACKET));
buffer.flush();
}
break;
default:
buffer.append(current);
break;
}
} while (hasNext());
if (!buffer.isEmpty()) {
buffer.flush();
}
for (Fragment f : buffer.getFragments()) {
System.out.println("Fragment: " + f.frag + " Type: " + f.type);
formalized.append(f.toString());
}
return formalized.toString();
}
private static class TokenBuffer {
private List<Fragment> fragments = new ArrayList<Fragment>();
private StringBuilder sb = new StringBuilder();
public TokenBuffer append(String s) {
sb.append(s);
return this;
}
public TokenBuffer append(char c) {
sb.append(c);
return this;
}
public void flush() {
fragments.add(new Fragment(Type.PROPERTY, sb.toString().trim()));
sb = new StringBuilder();
}
public boolean isEmpty() {
return sb.length() == 0;
}
public List<Fragment> getFragments() {
return fragments;
}
}
private Fragment createFragment(String data) {
if ("$".equals(data)) {
return ROOT;
} else if ("..".equals(data)) {
return SCAN;
} else if (isInts(data, true)) {
return new Fragment(Type.INDEX, new String(data));
} else {
return new Fragment(Type.PROPERTY, new String(data));
}
}
private static class Fragment {
private Type type;
private String frag;
private Fragment(Type type, String frag) {
this.type = type;
this.frag = frag;
}
/*
//"[-1:]" sliceFrom
//"[:1]" sliceTo
//"[0:5]" sliceBetween
//"[1]"
//"[1,2,3]"
//"[(@.length - 1)]"
*/
private static Fragment create(String str) {
boolean isProperty = str.startsWith("'") && str.endsWith("'");
if (isProperty) {
return new Fragment(Type.PROPERTY, new String(str.substring(1, str.length()-1)));
} else if ("$".equals(str)) {
return ROOT;
} else if ("..".equals(str)) {
return SCAN;
} else if ("*".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("-1:".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if (":1".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("1:2".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("1".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("1,2,3".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("(@.length() - 1)".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("?(@.foo == 'bar')".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else if ("1,2,3".equals(str)) {
return new Fragment(Type.INDEX, new String(str));
} else {
return new Fragment(Type.PROPERTY, new String(str));
}
}
@Override
public String toString() {
return frag;
}
}
private static enum Type {
ROOT,
SCAN,
PROPERTY,
INDEX
}
public static void main(String[] args) {
String path = "$.store['foo'].arr[10].monkey..book[?(@.isbn)].isbn";
System.out.println(path);
PathFormalizer p = new PathFormalizer(path);
String f = p.formalize();
System.out.println(f);
}
}

79
json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java

@ -1,79 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.InvalidModelException;
import com.jayway.jsonpath.internal.filter.FilterFactory;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Kalle Stenflo
*/
public class PathToken {
private static final Pattern ARRAY_INDEX_PATTERN = Pattern.compile("\\[(\\d+)]");
private final String fragment;
private final int tokenIndex;
private final boolean endToken;
public PathToken(String fragment, int tokenIndex, boolean isEndToken) {
this.fragment = fragment;
this.tokenIndex = tokenIndex;
this.endToken = isEndToken;
}
public PathTokenFilter getFilter(){
return FilterFactory.createFilter(this);
}
public Object filter(Object model, Configuration configuration){
return FilterFactory.createFilter(this).filter(model, configuration);
}
public Object apply(Object model, Configuration configuration){
return FilterFactory.createFilter(this).getRef(model, configuration);
}
public String getFragment() {
return fragment;
}
public boolean isRootToken(){
return this.tokenIndex == 0;
}
public boolean isEndToken(){
return this.endToken;
}
public boolean isArrayIndexToken(){
return ARRAY_INDEX_PATTERN.matcher(fragment).matches();
}
public int getArrayIndex(){
Matcher matcher = ARRAY_INDEX_PATTERN.matcher(fragment);
if(matcher.find()){
return Integer.parseInt(matcher.group(1));
}
else throw new InvalidModelException("Could not get array index from fragment " + fragment);
}
}

285
json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java

@ -1,285 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal;
import com.jayway.jsonpath.InvalidPathException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author Kalle Stenflo
*/
public class PathTokenizer implements Iterable<PathToken> {
private static Pattern INVALID_PATH_PATTERN = Pattern.compile("[^\\?\\+=\\-\\*/!]\\(");
private List<PathToken> pathTokens = new LinkedList<PathToken>();
private char[] pathChars;
private transient int index = 0;
public PathTokenizer(String jsonPath) {
if (INVALID_PATH_PATTERN.matcher(jsonPath).matches()) {
throw new InvalidPathException("Invalid path: " + jsonPath);
}
if (!jsonPath.startsWith("$") && !jsonPath.startsWith("$[")) {
jsonPath = "$." + jsonPath;
}
this.pathChars = jsonPath.toCharArray();
List<String> tokens = splitPath();
int len = tokens.size();
int i = 0;
for (String pathFragment : tokens) {
pathTokens.add(new PathToken(pathFragment, i, (i==(len-1)) ));
i++;
}
}
public List<String> getFragments() {
List<String> fragments = new LinkedList<String>();
for (PathToken pathToken : pathTokens) {
fragments.add(pathToken.getFragment());
}
return fragments;
}
public int size(){
return pathTokens.size();
}
public String getPath() {
return new String(pathChars);
}
public LinkedList<PathToken> getPathTokens(){
return new LinkedList<PathToken>(pathTokens);
}
public Iterator<PathToken> iterator() {
return pathTokens.iterator();
}
public PathToken removeLastPathToken(){
PathToken lastPathToken = pathTokens.get(pathTokens.size() - 1);
//TODO: this should also trim the pathChars
pathTokens.remove(pathTokens.size() - 1);
return lastPathToken;
}
//--------------------------------------------
//
// Split path
//
//--------------------------------------------
private boolean isEmpty() {
return index == pathChars.length;
}
private char peek() {
return pathChars[index];
}
private char poll() {
char peek = peek();
index++;
return peek;
}
public List<String> splitPath() {
List<String> fragments = new LinkedList<String>();
while (!isEmpty()) {
skip(' ');
char current = peek();
switch (current) {
case '$':
fragments.add(Character.toString(current));
poll();
break;
case '.':
poll();
if (!isEmpty() && peek() == '.') {
poll();
fragments.add("..");
assertNotInvalidPeek('.');
}
break;
case '[':
fragments.add(extract(true, ']'));
break;
default:
fragments.add(extract(false, '[', '.'));
}
}
return fragments;
}
private String extract(boolean includeSopChar, char... stopChars) {
StringBuilder sb = new StringBuilder();
while (!isEmpty() && (!isStopChar(peek(), stopChars))) {
if (peek() == '(') {
do {
sb.append(poll());
} while (peek() != ')');
sb.append(poll());
} else {
char c = poll();
if (isStopChar(c, stopChars)) {
if (includeSopChar) {
sb.append(c);
}
} else {
sb.append(c);
}
}
}
if (includeSopChar) {
assertValidPeek(false, stopChars);
sb.append(poll());
} else {
assertValidPeek(true, stopChars);
}
return clean(sb);
}
private String clean(StringBuilder sb) {
String src = sb.toString();
src = trim(src, "'");
src = trim(src, ")");
src = trim(src, "(");
src = trimLeft(src, "?");
src = trimLeft(src, "@");
if (src.length() >= 5 && src.subSequence(0, 2).equals("['")) {
src = src.substring(2);
src = src.substring(0, src.length() - 2);
}
return src.trim();
}
private String trim(String src, String trim) {
return trimLeft(trimRight(src, trim), trim);
}
private String trimRight(String src, String trim) {
String scanFor = trim + " ";
if (src.contains(scanFor)) {
while (src.contains(scanFor)) {
src = src.replace(scanFor, trim);
}
}
return src;
}
private String trimLeft(String src, String trim) {
String scanFor = " " + trim;
if (src.contains(scanFor)) {
while (src.contains(scanFor)) {
src = src.replace(scanFor, trim);
}
}
return src;
}
private boolean isStopChar(char c, char... scanFor) {
boolean found = false;
for (char check : scanFor) {
if (check == c) {
found = true;
break;
}
}
return found;
}
private void skip(char target) {
if (isEmpty()) {
return;
}
while (pathChars[index] == target) {
poll();
}
}
private void assertNotInvalidPeek(char... invalidChars) {
if (isEmpty()) {
return;
}
char peek = peek();
for (char check : invalidChars) {
if (check == peek) {
throw new InvalidPathException("Char: " + peek + " at current position is not valid!");
}
}
}
private void assertValidPeek(boolean acceptEmpty, char... validChars) {
if (isEmpty() && acceptEmpty) {
return;
}
if (isEmpty()) {
throw new InvalidPathException("Path is incomplete");
}
boolean found = false;
char peek = peek();
for (char check : validChars) {
if (check == peek) {
found = true;
break;
}
}
if (!found) {
throw new InvalidPathException("Path is invalid");
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("---------------------------------------------------------------------------").append("\n");
sb.append("PATH: ").append(getPath()).append("\n");
sb.append(String.format("%-50s%-10s%-10s%-10s", "Fragment", "Root", "End", "Array")).append("\n");
sb.append("---------------------------------------------------------------------------").append("\n");
for (PathToken pathToken : pathTokens) {
sb.append(String.format("%-50s%-10b%-10b%-10b", pathToken.getFragment(), pathToken.isRootToken(), pathToken.isEndToken(), pathToken.isArrayIndexToken())).append("\n");
}
return sb.toString();
}
}

101
json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java

@ -3,9 +3,49 @@ package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.InvalidConversionException;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Utils {
public static final String CR = System.getProperty("line.separator");
/**
* Creates a range of integers from start (inclusive) to end (exclusive)
*
* @param start
* @param end
* @return
*/
public static List<Integer> createRange(int start, int end) {
List<Integer> range = new ArrayList<Integer>();
for (int i = start; i < end; i++) {
range.add(i);
}
return range;
}
// accept a collection of objects, since all objects have toString()
public static String join(String delimiter, String wrap, Iterable<? extends Object> objs) {
Iterator<? extends Object> iter = objs.iterator();
if (!iter.hasNext()) {
return "";
}
StringBuilder buffer = new StringBuilder();
buffer.append(wrap).append(iter.next()).append(wrap);
while (iter.hasNext()) {
buffer.append(delimiter).append(wrap).append(iter.next()).append(wrap);
}
return buffer.toString();
}
// accept a collection of objects, since all objects have toString()
public static String join(String delimiter, Iterable<? extends Object> objs) {
return join(delimiter, "", objs);
}
//---------------------------------------------------------
//
// IO
@ -17,7 +57,8 @@ public class Utils {
if (closeable != null) {
closeable.close();
}
} catch (IOException ignore) {}
} catch (IOException ignore) {
}
}
//---------------------------------------------------------
@ -25,10 +66,35 @@ public class Utils {
// Strings
//
//---------------------------------------------------------
public static boolean isInt(String str) {
if (str == null) {
return false;
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
if (Character.isDigit(str.charAt(i)) == false) {
return false;
}
}
return true;
}
public static boolean isNumeric(String str) {
if (str == null) {
return false;
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
if (Character.isDigit(str.charAt(i)) == false && !(str.charAt(i) == '.')) {
return false;
}
}
return true;
}
/**
* <p>Checks if a CharSequence is empty ("") or null.</p>
*
* <p/>
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
@ -36,7 +102,7 @@ public class Utils {
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p/>
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence.
* That functionality is available in isBlank().</p>
@ -63,9 +129,9 @@ public class Utils {
/**
* <p>Counts how many times the substring appears in the larger string.</p>
*
* <p/>
* <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
*
* <p/>
* <pre>
* StringUtils.countMatches(null, *) = 0
* StringUtils.countMatches("", *) = 0
@ -103,7 +169,7 @@ public class Utils {
/**
* <p>Validate that the specified argument is not {@code null};
* otherwise throwing an exception with the specified message.
*
* <p/>
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
*
* @param <T> the object type
@ -125,9 +191,9 @@ public class Utils {
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <p/>
* <pre>Validate.isTrue(i > 0.0, "The value must be greater than zero: %d", i);</pre>
*
* <p/>
* <p>For performance reasons, the long value is passed as a separate parameter and
* appended to the exception message only in the case of an error.</p>
*
@ -145,7 +211,7 @@ public class Utils {
* <p>Validate that the specified argument character sequence is
* neither {@code null} nor a length of zero (no characters);
* otherwise throwing an exception with the specified message.
*
* <p/>
* <pre>Validate.notEmpty(myString, "The string must not be empty");</pre>
*
* @param <T> the character sequence type
@ -167,12 +233,12 @@ public class Utils {
}
//---------------------------------------------------------
//
// Converters
//
//---------------------------------------------------------
/**
* converts to Integer with radix 10
*
@ -244,7 +310,7 @@ public class Utils {
/**
* <p>Deep clone an {@code Object} using serialization.</p>
*
* <p/>
* <p>This is many times slower than writing clone methods by hand
* on all objects in your object graph. However, for complex object
* graphs, or for those that don't support deep cloning this can
@ -293,11 +359,11 @@ public class Utils {
/**
* <p>Serializes an {@code Object} to the specified stream.</p>
*
* <p/>
* <p>The stream will be closed once the object is written.
* This avoids the need for a finally clause, and maybe also exception
* handling, in the application code.</p>
*
* <p/>
* <p>The stream passed in is not buffered internally within this method.
* This is the responsibility of your application if desired.</p>
*
@ -345,13 +411,14 @@ public class Utils {
// Deserialize
//-----------------------------------------------------------------------
/**
* <p>Deserializes an {@code Object} from the specified stream.</p>
*
* <p/>
* <p>The stream will be closed once the object is written. This
* avoids the need for a finally clause, and maybe also exception
* handling, in the application code.</p>
*
* <p/>
* <p>The stream passed in is not buffered internally within this method.
* This is the responsibility of your application if desired.</p>
*
@ -410,7 +477,7 @@ public class Utils {
* containers and application servers, no matter in which of the
* <code>ClassLoader</code> the particular class that encapsulates
* serialization/deserialization lives. </p>
*
* <p/>
* <p>For more in-depth information about the problem for which this
* class here is a workaround, see the JIRA issue LANG-626. </p>
*/
@ -419,6 +486,7 @@ public class Utils {
/**
* Constructor.
*
* @param in The <code>InputStream</code>.
* @param classLoader classloader to use
* @throws IOException if an I/O error occurs while reading stream header.
@ -432,6 +500,7 @@ public class Utils {
/**
* Overriden version that uses the parametrized <code>ClassLoader</code> or the <code>ClassLoader</code>
* of the current <code>Thread</code> to resolve the class.
*
* @param desc An instance of class <code>ObjectStreamClass</code>.
* @return A <code>Class</code> object corresponding to <code>desc</code>.
* @throws IOException Any of the usual Input/Output exceptions.

201
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java

@ -1,201 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.filter.eval.ExpressionEvaluator;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Kalle Stenflo
*/
public class ArrayEvalFilter extends PathTokenFilter {
private static final Pattern CONDITION_STATEMENT_PATTERN = Pattern.compile("\\[\\s?\\?\\(.*?[!=<>]+.*?\\)\\s?]");
private static final Pattern PATTERN = Pattern.compile("\\s?(@.*?)\\s?([!=<>]+)\\s?(.*?)\\s?");
private ConditionStatement[] conditionStatements;
public ArrayEvalFilter(String condition) {
super(condition);
// [?(@.name == 'Luke Skywalker' && @.occupation == 'Farm boy')]
// [?(@.name == 'Luke Skywalker')]
condition = condition.trim();
condition = condition.substring(3, condition.length()-2);
String[] split = condition.split("&&");
conditionStatements = new ConditionStatement[split.length];
for(int i = 0; i < split.length; i++){
conditionStatements[i] = createConditionStatement(split[i]);
}
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Iterable<Object> src = null;
try {
src = jsonProvider.toIterable(obj);
} catch (ClassCastException e){
throw new PathNotFoundException("The path fragment '" + this.condition + "' can not be applied to a JSON object only a JSON array.", e);
}
Object result = jsonProvider.createArray();
for (Object item : src) {
if (isMatch(item, configuration, conditionStatements)) {
jsonProvider.setProperty(result, jsonProvider.length(result), item);
}
}
return result;
}
@Override
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException("");
}
@Override
public boolean isArrayFilter() {
return true;
}
private boolean isMatch(Object check, Configuration configuration, ConditionStatement... conditionStatements) {
try {
for (ConditionStatement conditionStatement : conditionStatements) {
Object value = conditionStatement.path.read(check, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
boolean match = ExpressionEvaluator.eval(value, conditionStatement.getOperator(), conditionStatement.getExpected());
if(!match){
return false;
}
}
return true;
} catch (PathNotFoundException e){
return false;
} catch (RuntimeException e){
throw e;
}
}
static boolean isConditionStatement(String condition) {
return CONDITION_STATEMENT_PATTERN.matcher(condition).matches();
}
static ConditionStatement createConditionStatement(String condition) {
Matcher matcher = PATTERN.matcher(condition);
if (matcher.matches()) {
String property = matcher.group(1).trim();
String operator = matcher.group(2).trim();
String expected = matcher.group(3).trim();
return new ConditionStatement(condition, property, operator, expected);
} else {
return null;
}
}
static class ConditionStatement {
private final String condition;
private final String field;
private final String operator;
private final String expected;
private final JsonPath path;
ConditionStatement(String condition, String field, String operator, String expected) {
this.condition = condition;
this.field = field;
this.operator = operator;
if(expected.startsWith("'")){
this.expected = trim(expected, 1, 1);
}else{
this.expected = expected;
}
if(field.startsWith("@.")){
this.path = JsonPath.compile(this.field.replace("@.", "$."));
} else {
this.path = JsonPath.compile(this.field.replace("@", "$"));
}
}
ConditionStatement(String field, String operator, String expected) {
this(null, field, operator, expected);
}
String getCondition() {
return condition;
}
public JsonPath getJsonPath() {
return path;
}
public String getField() {
return field;
}
public String getOperator() {
return operator;
}
public String getExpected() {
return expected;
}
@Override
public String toString() {
return "ConditionStatement{" +
"field='" + field + '\'' +
", operator='" + operator + '\'' +
", expected='" + expected + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConditionStatement that = (ConditionStatement) o;
if (expected != null ? !expected.equals(that.expected) : that.expected != null) return false;
if (field != null ? !field.equals(that.field) : that.field != null) return false;
if (operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
return true;
}
@Override
public int hashCode() {
int result = field != null ? field.hashCode() : 0;
result = 31 * result + (operator != null ? operator.hashCode() : 0);
result = 31 * result + (expected != null ? expected.hashCode() : 0);
return result;
}
}
}

155
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java

@ -1,155 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.regex.Pattern;
/**
* @author Kalle Stenflo
*/
public class ArrayIndexFilter extends PathTokenFilter {
private static final Pattern SINGLE_ARRAY_INDEX_PATTERN = Pattern.compile("\\[\\d+\\]");
private static final Pattern COMMA = Pattern.compile(",");
private static final Pattern SPACE = Pattern.compile(" ");
private static final String OPERATOR = ":";
private final String trimmedCondition;
private boolean usesLenght;
public ArrayIndexFilter(String condition) {
super(condition);
// remove '[' and ']'
String trimmedCondition = trim(condition, 1, 1);
this.usesLenght = trimmedCondition.contains("@.length");
// resolve '@.length'
if(usesLenght){
trimmedCondition = trim(trimmedCondition, 1, 1);
trimmedCondition = trimmedCondition.replace("@.length", "");
trimmedCondition = trimmedCondition + OPERATOR;
}
this.trimmedCondition = trimmedCondition;
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
if (trimmedCondition.contains(OPERATOR)) {
if (trimmedCondition.startsWith(OPERATOR)) {
String trimmedCondition = trim(this.trimmedCondition, 1, 0);
int get = Integer.parseInt(trimmedCondition);
for (int i = 0; i < get; i++) {
try {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, i));
} catch (IndexOutOfBoundsException e){
break;
}
}
return result;
} else if (trimmedCondition.endsWith(OPERATOR)) {
String trimmedCondition = trim(SPACE.matcher(this.trimmedCondition).replaceAll(""), 0, 1);
int get = Integer.parseInt(trimmedCondition);
if(get > 0 || usesLenght){
if(get > 0){
get = get * -1;
}
return jsonProvider.getProperty(obj, jsonProvider.length(obj) + get);
} else {
int start = jsonProvider.length(obj) + get;
int stop = jsonProvider.length(obj);
if(start < 0){
start = 0;
}
for (int i = start; i < stop; i ++){
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, i));
}
return result;
}
} else {
String[] indexes = this.trimmedCondition.split(OPERATOR);
int start = Integer.parseInt(indexes[0]);
int stop = Integer.parseInt(indexes[1]);
for (int i = start; i < stop; i ++){
try {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, i));
} catch (IndexOutOfBoundsException e){
break;
}
}
return result;
}
} else {
String[] indexArr = COMMA.split(trimmedCondition);
//if(obj == null || jsonProvider.length(obj) == 0){
if(obj == null){
return result;
}
try {
if (indexArr.length == 1) {
/*
if(jsonProvider.length(obj) == 0){
throw new PathNotFoundException("Array index [" + indexArr[0] + "] not found in path");
}
*/
return jsonProvider.getProperty(obj, indexArr[0]);
} else {
for (String idx : indexArr) {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, idx.trim()));
}
return result;
}
} catch (IndexOutOfBoundsException e){
throw new PathNotFoundException("Array index " + indexArr + " not found in path", e);
}
}
}
@Override
public Object getRef(Object obj, Configuration configuration) {
if(SINGLE_ARRAY_INDEX_PATTERN.matcher(condition).matches()){
String trimmedCondition = trim(condition, 1, 1);
return configuration.getProvider().getProperty(obj, trimmedCondition);
} else {
throw new UnsupportedOperationException();
}
}
@Override
public boolean isArrayFilter() {
return true;
}
}

51
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayQueryFilter.java

@ -1,51 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import java.util.LinkedList;
/**
* @author Kalle Stenflo
*/
public class ArrayQueryFilter extends PathTokenFilter {
ArrayQueryFilter(String condition) {
super(condition);
}
@Override
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext) {
Filter filter = filters.poll();
return filter.doFilter(configuration.getProvider().toIterable(obj), configuration);
}
@Override
public Object filter(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}
@Override
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException("");
}
@Override
public boolean isArrayFilter() {
return true;
}
}

136
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java

@ -1,136 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.Collection;
import java.util.LinkedList;
/**
* @author Kalle Stenflo
*/
public class FieldFilter extends PathTokenFilter {
private final String[] split;
private final PathToken pathToken;
public FieldFilter(PathToken pathToken) {
super(pathToken.getFragment());
this.pathToken = pathToken;
this.split = condition.split("','");
}
@Override
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
if (!inArrayContext) {
throw new PathNotFoundException("Path '" + condition + "' is being applied to an array. Arrays can not have attributes.");
} else {
Object result = jsonProvider.createArray();
for (Object current : jsonProvider.toIterable(obj)) {
if (jsonProvider.isMap(current)) {
Collection<String> keys = jsonProvider.getPropertyKeys(current);
if(split.length == 1){
if (keys.contains(condition)) {
Object o = jsonProvider.getProperty(current, condition);
boolean isArr = jsonProvider.isArray(o);
boolean isEnd = pathToken.isEndToken();
if (isArr && !isEnd) {
for(Object item : jsonProvider.toIterable(o)){
jsonProvider.setProperty(result, jsonProvider.length(result), item);
}
} else {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(current, condition));
}
}
} else {
Object res = jsonProvider.createMap();
for (String prop : split) {
if (keys.contains(prop)) {
jsonProvider.setProperty(res, prop, jsonProvider.getProperty(current, prop));
}
}
jsonProvider.setProperty(result, jsonProvider.length(result), res);
}
}
}
return result;
}
} else if (jsonProvider.isMap(obj)){
Collection<String> keys = jsonProvider.getPropertyKeys(obj);
if(!keys.contains(condition) && split.length == 1){
if(configuration.getOptions().contains(Option.THROW_ON_MISSING_PROPERTY)){
throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
}
if(pathToken.isEndToken()){
return null;
} else {
throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
}
} else {
if(split.length == 1){
return jsonProvider.getProperty(obj, condition);
} else {
Object res = jsonProvider.createMap();
for (String prop : split) {
if(keys.contains(prop)){
jsonProvider.setProperty(res, prop, jsonProvider.getProperty(obj, prop));
}
}
return res;
}
}
} else {
throw new PathNotFoundException("Failed to access property: '" + condition + "' on object " + obj);
}
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
return obj;
} else {
return jsonProvider.getProperty(obj, condition);
}
}
@Override
public Object getRef(Object obj, Configuration configuration) {
return filter(obj, configuration);
}
@Override
public boolean isArrayFilter() {
return false;
}
}

85
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterFactory.java

@ -1,85 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.PathToken;
/**
* @author Kalle Stenflo
*/
public class FilterFactory {
private final static PathTokenFilter DOCUMENT_FILTER = new PassthroughFilter("$", false);
private final static PathTokenFilter ALL_ARRAY_ITEMS_FILTER = new PassthroughFilter("[*]", true);
private final static PathTokenFilter WILDCARD_FILTER = new WildcardFilter("*");
private final static PathTokenFilter SCAN_FILTER = new ScanFilter("..");
private final static PathTokenFilter ARRAY_QUERY_FILTER = new ArrayQueryFilter("[?]");
public static PathTokenFilter createFilter(PathToken token) {
String pathFragment = token.getFragment();
if (DOCUMENT_FILTER.getCondition().equals(pathFragment) && token.isRootToken()) { //"$"
return DOCUMENT_FILTER;
} else if (ALL_ARRAY_ITEMS_FILTER.getCondition().equals(pathFragment)) { //"[*]"
return ALL_ARRAY_ITEMS_FILTER;
} else if ("*".equals(pathFragment)) {
return WILDCARD_FILTER;
} else if (SCAN_FILTER.getCondition().equals(pathFragment)) {
return SCAN_FILTER;
} else if (ARRAY_QUERY_FILTER.getCondition().equals(pathFragment)) { //"[?]"
return ARRAY_QUERY_FILTER;
} else if (!pathFragment.contains("[")) {
return new FieldFilter(token);
} else if (pathFragment.contains("[")) {
if (pathFragment.startsWith("[?")) {
if(ArrayEvalFilter.isConditionStatement(pathFragment)){
return new ArrayEvalFilter(pathFragment);
} else if (!pathFragment.contains("=") && !pathFragment.contains("<") && !pathFragment.contains(">")) {
//[?(@.isbn)]
return new HasPathFilter(pathFragment);
} else {
throw new InvalidPathException("Failed to create PathTokenFilter for path fragment: " + pathFragment);
}
} else {
//[0]
//[0,1, ...]
//[-1:]
//[:1]
return new ArrayIndexFilter(pathFragment);
}
}
throw new UnsupportedOperationException("can not find filter for path fragment " + pathFragment);
}
}

72
json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasPathFilter.java

@ -1,72 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.spi.JsonProvider;
/**
* @author Kalle Stenflo
*/
public class HasPathFilter extends PathTokenFilter {
private final JsonPath path;
public HasPathFilter(String condition) {
super(condition);
String trimmedCondition = condition;
if(condition.contains("['")){
trimmedCondition = trimmedCondition.replace("['", ".");
trimmedCondition = trimmedCondition.replace("']", "");
}
this.path = JsonPath.compile(trim(trimmedCondition, 5, 2));
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
//[?(@.isbn)]
Iterable<Object> src = jsonProvider.toIterable(obj);
Object result = jsonProvider.createArray();
for (Object item : src) {
if(jsonProvider.isMap(item)){
try{
path.read(item, Configuration.builder().options(Option.THROW_ON_MISSING_PROPERTY).jsonProvider(jsonProvider).build());
jsonProvider.setProperty(result, jsonProvider.length(result), item);
} catch (PathNotFoundException e){
// the path was not found in the item
}
}
}
return result;
}
@Override
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}
@Override
public boolean isArrayFilter() {
return true;
}
}

46
json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java

@ -1,46 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
/**
* @author Kalle Stenflo
*/
public class PassthroughFilter extends PathTokenFilter {
private boolean isArrayFilter;
public PassthroughFilter(String condition, boolean isArrayFilter) {
super(condition);
this.isArrayFilter = isArrayFilter;
}
@Override
public Object filter(Object obj, Configuration configuration) {
return obj;
}
@Override
public Object getRef(Object obj, Configuration configuration) {
return obj;
}
@Override
public boolean isArrayFilter() {
return isArrayFilter;
}
}

70
json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java

@ -1,70 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import java.util.LinkedList;
/**
* @author Kalle Stenflo
*/
public abstract class PathTokenFilter {
final String condition;
PathTokenFilter(String condition) {
this.condition = condition;
}
String getCondition() {
return condition;
}
static String trim(String str, int front, int end) {
String res = str;
if (front > 0) {
res = str.substring(front);
}
if (end > 0) {
res = res.substring(0, res.length() - end);
}
return res;
}
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext){
return filter(obj, configuration);
}
public abstract Object filter(Object obj, Configuration configuration);
public abstract Object getRef(Object obj, Configuration configuration);
public abstract boolean isArrayFilter();
@Override
public String toString() {
if(isArrayFilter()){
return getClass().getSimpleName() + " => " + condition;
} else {
return getClass().getSimpleName() + " => '" + condition + "'";
}
}
}

62
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java

@ -1,62 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
/**
* @author Kalle Stenflo
*/
public class ScanFilter extends PathTokenFilter {
public ScanFilter(String condition) {
super(condition);
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
scan(obj, result, jsonProvider);
return result;
}
@Override
public boolean isArrayFilter() {
return true;
}
@Override
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}
private void scan(Object container, Object result, JsonProvider jsonProvider) {
if (jsonProvider.isMap(container)) {
jsonProvider.setProperty(result, jsonProvider.length(result), container);
}
for (Object value : jsonProvider.toIterable(container)) {
if (jsonProvider.isContainer(value)) {
scan(value, result, jsonProvider);
}
}
}
}

57
json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java

@ -1,57 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
/**
* @author Kalle Stenflo
*/
public class WildcardFilter extends PathTokenFilter {
public WildcardFilter(String condition) {
super(condition);
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
if (jsonProvider.isArray(obj)) {
for (Object current : jsonProvider.toIterable(obj)) {
for (Object value : jsonProvider.toIterable(current)) {
jsonProvider.setProperty(result, jsonProvider.length(result), value);
}
}
} else {
for (Object value : jsonProvider.toIterable(obj)) {
jsonProvider.setProperty(result, jsonProvider.length(result), value);
}
}
return result;
}
@Override
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}
@Override
public boolean isArrayFilter() {
return true;
}
}

243
json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java

@ -1,243 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.internal.filter.eval;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* @author Kalle Stenflo
*/
public class ExpressionEvaluator {
private static final String NULL_VALUE = "null";
public enum Operator {
equal("=="),
not_equal("!="),
less_or_greater_than("<>"), //same as not_equal
greater_than(">"),
greater_than_or_equal(">="),
less_than("<"),
less_than_or_equal("<=");
private final String representation;
private Operator(String representation) {
this.representation = representation;
}
public String getRepresentation() {
return representation;
}
}
private static Map<String, Operator> operatorsByRepresentation;
static {
Map<String, Operator> map = new HashMap<String, Operator>();
for (Operator op : Operator.values()) {
map.put(op.getRepresentation(), op);
}
ExpressionEvaluator.operatorsByRepresentation = Collections.unmodifiableMap(map);
}
public static <T> boolean eval(T actual, String comparator, String expected) {
Operator operator = operatorsByRepresentation.get(comparator);
if (operator == null) {
throw new IllegalArgumentException("Unsupported operator " + comparator);
}
if(actual == null){
if(operator == Operator.equal){
return NULL_VALUE.equals(expected);
} else if(operator == Operator.not_equal || operator == Operator.less_or_greater_than){
return !NULL_VALUE.equals(expected);
}
} else {
if(operator == Operator.not_equal || operator == Operator.less_or_greater_than){
if(NULL_VALUE.equals(expected)){
return true;
}
}
}
if (actual instanceof Long) {
Long a = (Long) actual;
Long e = Long.parseLong(expected.trim());
switch (operator) {
case equal:
return a.longValue() == e.longValue();
case not_equal:
case less_or_greater_than:
return a.longValue() != e.longValue();
case greater_than:
return a > e;
case greater_than_or_equal:
return a >= e;
case less_than:
return a < e;
case less_than_or_equal:
return a <= e;
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof Integer) {
Integer a = (Integer) actual;
Integer e = Integer.parseInt(expected.trim());
switch (operator) {
case equal:
return a.intValue() == e.intValue();
case not_equal:
case less_or_greater_than:
return a.intValue() != e.intValue();
case greater_than:
return a > e;
case greater_than_or_equal:
return a >= e;
case less_than:
return a < e;
case less_than_or_equal:
return a <= e;
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof Double) {
Double a = (Double) actual;
Double e = Double.parseDouble(expected.trim());
switch (operator) {
case equal:
return a.doubleValue() == e.doubleValue();
case not_equal:
case less_or_greater_than:
return a.doubleValue() != e.doubleValue();
case greater_than:
return a > e;
case greater_than_or_equal:
return a >= e;
case less_than:
return a < e;
case less_than_or_equal:
return a <= e;
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof String) {
switch (operator) {
case greater_than:
case greater_than_or_equal:
case less_than:
case less_than_or_equal:
// we might want to throw an exception here
return false;
case equal:
case not_equal:
case less_or_greater_than:
String a = (String) actual;
String expectedTrimmed = expected.trim();
if (expectedTrimmed.startsWith("'")) {
expectedTrimmed = expectedTrimmed.substring(1);
}
if (expectedTrimmed.endsWith("'")) {
expectedTrimmed = expectedTrimmed.substring(0, expected.length() - 1);
}
if (operator == Operator.equal) {
return a.equals(expectedTrimmed);
} else if (operator == Operator.not_equal || operator == Operator.less_or_greater_than) {
return !a.equals(expectedTrimmed);
}
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof Boolean) {
switch (operator) {
case equal:
case not_equal:
case less_or_greater_than:
Boolean a = (Boolean) actual;
Boolean e = Boolean.valueOf(expected);
if (operator == Operator.equal) {
return a.equals(e);
} else if (operator == Operator.not_equal || operator == Operator.less_or_greater_than) {
return !a.equals(e);
}
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof BigInteger) {
BigInteger a = (BigInteger) actual;
BigInteger e = new BigInteger(expected.trim());
switch (operator) {
case equal:
return a.compareTo(e) == 0;
case not_equal:
return a.compareTo(e) != 0;
case less_or_greater_than:
return a.compareTo(e) != 0;
case greater_than:
return a.compareTo(e) > 0;
case greater_than_or_equal:
return a.compareTo(e) >= 0;
case less_than:
return a.compareTo(e) < 0;
case less_than_or_equal:
return a.compareTo(e) <= 0;
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
} else if (actual instanceof BigDecimal) {
BigDecimal a = (BigDecimal) actual;
BigDecimal e = new BigDecimal(expected);
switch (operator) {
case equal:
return a.compareTo(e) == 0;
case not_equal:
return a.compareTo(e) != 0;
case less_or_greater_than:
return a.compareTo(e) != 0;
case greater_than:
return a.compareTo(e) > 0;
case greater_than_or_equal:
return a.compareTo(e) >= 0;
case less_than:
return a.compareTo(e) < 0;
case less_than_or_equal:
return a.compareTo(e) <= 0;
default:
throw new UnsupportedOperationException("Cannot handle operator " + operator);
}
}
return false;
}
}

155
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ArrayPathToken.java

@ -0,0 +1,155 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import static java.lang.String.format;
/**
*
*/
class ArrayPathToken extends PathToken {
private static final Logger logger = LoggerFactory.getLogger(ArrayPathToken.class);
public static enum Operation {
CONTEXT_SIZE,
SLICE_TO,
SLICE_FROM,
SLICE_BETWEEN,
INDEX_SEQUENCE,
SINGLE_INDEX;
}
private final List<Integer> criteria;
private final Operation operation;
private final boolean isDefinite;
public ArrayPathToken(List<Integer> criteria, Operation operation) {
this.criteria = criteria;
this.operation = operation;
this.isDefinite = (Operation.SINGLE_INDEX == operation || Operation.CONTEXT_SIZE == operation);
}
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (!ctx.jsonProvider().isArray(model)) {
throw new InvalidPathException(format("Filter: %s can only be applied to arrays. Current context is: %s", toString(), model));
}
try {
if (operation == Operation.SINGLE_INDEX) {
handleArrayIndex(criteria.get(0), currentPath, model, ctx);
} else if (operation == Operation.INDEX_SEQUENCE) {
for (Integer idx : criteria) {
handleArrayIndex(criteria.get(idx), currentPath, model, ctx);
}
} else if (Operation.CONTEXT_SIZE == operation) {
int length = ctx.jsonProvider().length(model);
int idx = length + criteria.get(0);
handleArrayIndex(idx, currentPath, model, ctx);
}
//[2:]
else if (Operation.SLICE_FROM == operation) {
int input = criteria.get(0);
int length = ctx.jsonProvider().length(model);
int from = input;
if (from < 0) {
//calculate slice start from array length
from = length + from;
}
from = Math.max(0, from);
logger.debug("Slice from index on array with length: {}. From index: {} to: {}. Input: {}", length, from, length - 1, toString());
if (length == 0 || from >= length) {
return;
}
for (int i = from; i < length; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
//[:2]
else if (Operation.SLICE_TO == operation) {
int input = criteria.get(0);
int length = ctx.jsonProvider().length(model);
int to = input;
if (to < 0) {
//calculate slice end from array length
to = length + to;
}
to = Math.min(length, to);
logger.debug("Slice to index on array with length: {}. From index: 0 to: {}. Input: {}", length, to, toString());
if (length == 0) {
return;
}
for (int i = 0; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
//[2:4]
else if (Operation.SLICE_BETWEEN == operation) {
int from = criteria.get(0);
int to = criteria.get(1);
int length = ctx.jsonProvider().length(model);
to = Math.min(length, to);
if (from >= to || length == 0) {
return;
}
logger.debug("Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}", length, from, to, toString());
for (int i = from; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
} catch (IndexOutOfBoundsException e) {
throw new PathNotFoundException(e);
}
}
@Override
public String getPathFragment() {
StringBuilder sb = new StringBuilder();
if (Operation.SINGLE_INDEX == operation || Operation.INDEX_SEQUENCE == operation) {
sb.append("[")
.append(Utils.join(",", "", criteria))
.append("]");
} else if (Operation.CONTEXT_SIZE == operation) {
sb.append("[@.size()")
.append(criteria.get(0))
.append("]");
} else if (Operation.SLICE_FROM == operation) {
sb.append("[")
.append(criteria.get(0))
.append(":]");
} else if (Operation.SLICE_TO == operation) {
sb.append("[:")
.append(criteria.get(0))
.append("]");
} else if (Operation.SLICE_BETWEEN == operation) {
sb.append("[")
.append(criteria.get(0))
.append(":")
.append(criteria.get(1))
.append("]");
} else
sb.append("NOT IMPLEMENTED");
return sb.toString();
}
@Override
boolean isTokenDefinite() {
return isDefinite;
}
}

51
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/CompiledPath.java

@ -0,0 +1,51 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.internal.JsonFormatter;
import com.jayway.jsonpath.spi.compiler.EvaluationContext;
import com.jayway.jsonpath.spi.compiler.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class CompiledPath implements Path {
private static final Logger logger = LoggerFactory.getLogger(CompiledPath.class);
private final PathToken root;
public CompiledPath(PathToken root) {
this.root = root;
}
@Override
public EvaluationContext evaluate(Object model, Configuration configuration) {
if(logger.isDebugEnabled()) {
logger.debug("Evaluating path: {}", toString());
}
EvaluationContextImpl ctx = new EvaluationContextImpl(configuration, isDefinite());
root.evaluate("", model, ctx);
if(logger.isDebugEnabled()) {
logger.debug("Found:\n{}", JsonFormatter.prettyPrint(ctx.configuration().getProvider().toJson(ctx.getPathList())));
}
return ctx;
}
@Override
public boolean isDefinite() {
return root.isPathDefinite();
}
@Override
public int tokenCount() {
return root.getTokenCount();
}
@Override
public String toString() {
return root.toString();
}
}

63
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/EvaluationContextImpl.java

@ -0,0 +1,63 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.compiler.EvaluationContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
*
*/
class EvaluationContextImpl implements EvaluationContext {
private final Configuration configuration;
private final Object objectResult;
private final List<String> pathResult;
private final boolean isDefinite;
private int resultIndex = 0;
EvaluationContextImpl(Configuration configuration, boolean isDefinite) {
this.configuration = configuration;
this.objectResult = configuration.getProvider().createArray();
this.pathResult = new ArrayList<String>();
this.isDefinite = isDefinite;
}
void addResult(String path, Object model) {
pathResult.add(path);
configuration.getProvider().setProperty(objectResult, resultIndex, model);
resultIndex++;
}
public JsonProvider jsonProvider() {
return configuration.getProvider();
}
public Set<Option> options() {
return configuration.getOptions();
}
@Override
public Configuration configuration() {
return configuration;
}
@Override
public <T> T get() {
if (isDefinite) {
return (T) jsonProvider().getProperty(objectResult, 0);
}
return (T) objectResult;
}
@Override
public List<String> getPathList() {
return pathResult;
}
}

74
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/FilterPathToken.java

@ -0,0 +1,74 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Filter2;
import com.jayway.jsonpath.InvalidPathException;
import java.util.Collection;
import static java.lang.String.format;
import static java.util.Arrays.asList;
/**
*
*/
class FilterPathToken extends PathToken {
private static final String[] FRAGMENTS = {
"[?]",
"[?,?]",
"[?,?,?]",
"[?,?,?,?]",
"[?,?,?,?,?]"
};
private final Collection<Filter2> filters;
public FilterPathToken(Filter2 filter) {
this.filters = asList(filter);
}
public FilterPathToken(Collection<Filter2> filters) {
this.filters = filters;
}
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (!ctx.jsonProvider().isArray(model)) {
throw new InvalidPathException(format("Filter: %s can only be applied to arrays. Current context is: %s", toString(), model));
}
int idx = 0;
Iterable<Object> objects = ctx.jsonProvider().toIterable(model);
for (Object idxModel : objects) {
if (accept(idxModel, ctx.configuration())) {
handleArrayIndex(idx, currentPath, model, ctx);
}
idx++;
}
}
public boolean accept(Object obj, Configuration configuration) {
boolean accept = true;
for (Filter2 filter : filters) {
if (!filter.apply (obj, configuration)) {
accept = false;
break;
}
}
return accept;
}
@Override
public String getPathFragment() {
return FRAGMENTS[filters.size() - 1];
}
@Override
boolean isTokenDefinite() {
return false;
}
}

530
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathCompiler.java

@ -0,0 +1,530 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Criteria;
import com.jayway.jsonpath.Criteria2;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Filter2;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.Cache;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.spi.compiler.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.Utils.notEmpty;
import static java.util.Arrays.asList;
public class PathCompiler {
private static final Logger logger = LoggerFactory.getLogger(PathCompiler.class);
private static final String PROPERTY_OPEN = "['";
private static final String PROPERTY_CLOSE = "']";
private static final char DOCUMENT = '$';
private static final char ANY = '*';
private static final char PERIOD = '.';
private static final char BRACKET_OPEN = '[';
private static final char BRACKET_CLOSE = ']';
private static final Cache cache = new Cache(200);
public static Path tokenize(String path, Filter2... filters) {
notEmpty(path, "Path may not be null empty");
path = path.trim();
LinkedList<Filter2> filterList = new LinkedList<Filter2>(asList(filters));
if (!path.startsWith("$")) {
path = "$." + path;
}
Path p = cache.get(path + filterList.toString());
if(p != null){
return p;
}
RootPathToken root = null;
char[] chars = path.toCharArray();
int i = 0;
int positions;
String fragment = "";
do {
char current = chars[i];
switch (current) {
case DOCUMENT:
fragment = "$";
i++;
break;
case BRACKET_OPEN:
positions = fastForwardUntilClosed(chars, i);
fragment = new String(chars, i, positions);
i += positions;
break;
case PERIOD:
i++;
if (chars[i] == PERIOD) {
//This is a deep scan
fragment = "..";
i++;
} else {
positions = fastForward(chars, i);
if (positions == 0) {
continue;
} else if (positions == 1 && chars[i] == '*') {
fragment = new String("[*]");
} else {
assertValidFieldChars(chars, i, positions);
fragment = PROPERTY_OPEN + new String(chars, i, positions) + PROPERTY_CLOSE;
}
i += positions;
}
break;
case ANY:
fragment = new String("[*]");
i++;
break;
default:
positions = fastForward(chars, i);
fragment = PROPERTY_OPEN + new String(chars, i, positions) + PROPERTY_CLOSE;
i += positions;
break;
}
if (root == null) {
root = (RootPathToken) PathComponentAnalyzer.analyze(fragment, filterList);
} else {
root.append(PathComponentAnalyzer.analyze(fragment, filterList));
}
} while (i < chars.length);
Path pa = new CompiledPath(root);
cache.put(path, pa);
return pa;
}
private static void assertValidFieldChars(char[] chars, int start, int positions) {
int i = start;
while (i < start + positions) {
char c = chars[i];
if (!Character.isLetterOrDigit(c) && c != '-' && c != '_' && c != '$' && c != '@') {
throw new InvalidPathException("Invalid field name! Use bracket notation if your filed names does not match pattern: ([a-zA-Z@][a-zA-Z0-9@\\$_\\-]*)$");
}
i++;
}
}
private static int fastForward(char[] chars, int index) {
int skipCount = 0;
while (index < chars.length) {
char current = chars[index];
if (current == PERIOD || current == BRACKET_OPEN) {
break;
}
index++;
skipCount++;
}
return skipCount;
}
private static int fastForwardUntilClosed(char[] chars, int index) {
int skipCount = 0;
int nestedBrackets = 0;
//First char is always '[' no need to check it
index++;
skipCount++;
while (index < chars.length) {
char current = chars[index];
index++;
skipCount++;
if (current == BRACKET_CLOSE && nestedBrackets == 0) {
break;
}
if (current == BRACKET_OPEN) {
nestedBrackets++;
}
if (current == BRACKET_CLOSE) {
nestedBrackets--;
}
}
return skipCount;
}
//---------------------------------------------
//
//
//
//---------------------------------------------
static class PathComponentAnalyzer {
private static final Pattern FILTER_PATTERN = Pattern.compile("^\\[\\s*\\?\\s*[,\\s*\\?]*?\\s*]$"); //[?] or [?, ?, ...]
private char[] chars;
private int i;
private char current;
private final LinkedList<Filter2> filterList;
private final String pathFragment;
PathComponentAnalyzer(String pathFragment, LinkedList<Filter2> filterList) {
this.pathFragment = pathFragment;
this.filterList = filterList;
}
static PathToken analyze(String pathFragment, LinkedList<Filter2> filterList) {
return new PathComponentAnalyzer(pathFragment, filterList).analyze();
}
public PathToken analyze() {
if ("$".equals(pathFragment)) return new RootPathToken();
else if ("..".equals(pathFragment)) return new ScanPathToken();
else if ("[*]".equals(pathFragment)) return new WildcardPathToken();
else if (".*".equals(pathFragment)) return new WildcardPathToken();
else if ("[?]".equals(pathFragment)) return new FilterPathToken(filterList.poll());
else if (FILTER_PATTERN.matcher(pathFragment).matches()) {
final int criteriaCount = Utils.countMatches(pathFragment, "?");
List<Filter2> filters = new ArrayList<Filter2>(criteriaCount);
for (int i = 0; i < criteriaCount; i++) {
filters.add(filterList.poll());
}
return new FilterPathToken(filters);
}
this.chars = pathFragment.toCharArray();
this.i = 0;
do {
current = chars[i];
switch (current) {
case '?':
return analyzeCriteriaSequence();
case '\'':
return analyzeProperty();
default:
if (Character.isDigit(current) || current == ':' || current == '-' || current == '@') {
return analyzeArraySequence();
}
i++;
break;
}
} while (i < chars.length);
throw new InvalidPathException("Could not analyze path component: " + pathFragment);
}
//[?(@.foo)]
//[?(@['foo'])]
//[?(@.foo == 'bar')]
//[?(@['foo']['bar'] == 'bar')]
//[?(@ == 'bar')]
private PathToken analyzeCriteriaSequence() {
StringBuilder pathBuffer = new StringBuilder();
StringBuilder operatorBuffer = new StringBuilder();
StringBuilder valueBuffer = new StringBuilder();
List<Criteria2> criteria = new ArrayList<Criteria2>();
int bracketCount = 0;
boolean functionBracketOpened = false;
boolean functionBracketClosed = false;
current = chars[++i]; //skip the '?'
while (current != ']' || bracketCount != 0) {
switch (current) {
case '(':
functionBracketOpened = true;
break;
case ')':
functionBracketClosed = true;
break;
case '[':
bracketCount++;
pathBuffer.append(current);
break;
case ']':
bracketCount--;
pathBuffer.append(current);
break;
case '@':
pathBuffer.append('$');
break;
default:
if (bracketCount == 0 && isOperatorChar(current)) {
operatorBuffer.append(current);
} else if (bracketCount == 0 && isLogicOperatorChar(current)) {
if (isLogicOperatorChar(chars[i + 1])) {
char op1 = current;
char op2 = chars[++i];
}
criteria.add(createCriteria(pathBuffer, operatorBuffer, valueBuffer));
pathBuffer = new StringBuilder();
operatorBuffer = new StringBuilder();
valueBuffer = new StringBuilder();
} else if (operatorBuffer.length() > 0) {
valueBuffer.append(current);
} else {
pathBuffer.append(current);
}
break;
}
current = chars[++i];
}
if (!functionBracketOpened || !functionBracketClosed) {
throw new InvalidPathException("Function wrapping brackets are not matching. A filter function must match [?(<statement>)]");
}
criteria.add(createCriteria(pathBuffer, operatorBuffer, valueBuffer));
/*
Iterator<Criteria2> iterator = criteria.iterator();
Criteria2 current = iterator.next();
Filter2 filter = Filter2.filter(current);
while (iterator.hasNext()) {
filter. addCriteria(iterator.next());
}
return new FilterPathToken(filter);
*/
Filter2 filter2 = Filter2.filter(criteria);
return new FilterPathToken(filter2);
}
private Criteria2 createCriteria(StringBuilder pathBuffer, StringBuilder operatorBuffer, StringBuilder valueBuffer) {
return Criteria2.create(pathBuffer.toString().trim(), operatorBuffer.toString().trim(), valueBuffer.toString().trim());
/*
String value = valueBuffer.toString().trim();
Path path = PathCompiler.tokenize(pathBuffer.toString().trim());
String operator = operatorBuffer.toString().trim();
if (operator.isEmpty() && value.isEmpty()) {
return Criteria.where(path).exists(true);
} else {
return Criteria.where(path).matches(operator, value);
}
*/
}
private boolean isAnd(char c) {
return c == '&';
}
private boolean isOr(char c) {
if (c == '|') {
throw new UnsupportedOperationException("OR operator is not supported.");
}
return false;
}
private boolean isLogicOperatorChar(char c) {
return isAnd(c) || isOr(c);
}
private boolean isOperatorChar(char c) {
return c == '=' || c == '!' || c == '<' || c == '>';
}
//"['foo']"
private PathToken analyzeProperty() {
String property = null;
StringBuilder buffer = new StringBuilder();
boolean propertyIsOpen = false;
while (current != ']') {
switch (current) {
case '\'':
if (propertyIsOpen) {
property = buffer.toString();
propertyIsOpen = false;
} else {
propertyIsOpen = true;
}
break;
default:
if (propertyIsOpen) {
buffer.append(current);
}
break;
}
current = chars[++i];
}
return new PropertyPathToken(property);
}
//"[-1:]" sliceFrom
//"[:1]" sliceTo
//"[0:5]" sliceBetween
//"[1]"
//"[1,2,3]"
//"[(@.length - 1)]"
private PathToken analyzeArraySequence() {
StringBuilder buffer = new StringBuilder();
List<Integer> numbers = new ArrayList<Integer>();
boolean contextSize = (current == '@');
boolean sliceTo = false;
boolean sliceFrom = false;
boolean sliceBetween = false;
boolean indexSequence = false;
boolean singleIndex = false;
if (contextSize) {
current = chars[++i];
current = chars[++i];
while (current != '-') {
if (current == ' ' || current == '(' || current == ')') {
current = chars[++i];
continue;
}
buffer.append(current);
current = chars[++i];
}
String function = buffer.toString();
buffer = new StringBuilder();
if (!function.equals("size") && !function.equals("length")) {
throw new InvalidPathException("Invalid function: @." + function + ". Supported functions are: [(@.length - n)] and [(@.size() - n)]");
}
while (current != ')') {
if (current == ' ') {
current = chars[++i];
continue;
}
buffer.append(current);
current = chars[++i];
}
} else {
while (Character.isDigit(current) || current == ',' || current == ' ' || current == ':' || current == '-') {
switch (current) {
case ' ':
break;
case ':':
if (buffer.length() == 0) {
//this is a tail slice [:12]
sliceTo = true;
current = chars[++i];
while (Character.isDigit(current) || current == ' ' || current == '-') {
if (current != ' ') {
buffer.append(current);
}
current = chars[++i];
}
numbers.add(Integer.parseInt(buffer.toString()));
buffer = new StringBuilder();
} else {
//we now this starts with [12:???
numbers.add(Integer.parseInt(buffer.toString()));
buffer = new StringBuilder();
current = chars[++i];
//this is a tail slice [:12]
while (Character.isDigit(current) || current == ' ' || current == '-') {
if (current != ' ') {
buffer.append(current);
}
current = chars[++i];
}
if (buffer.length() == 0) {
sliceFrom = true;
} else {
sliceBetween = true;
numbers.add(Integer.parseInt(buffer.toString()));
buffer = new StringBuilder();
}
}
break;
case ',':
numbers.add(Integer.parseInt(buffer.toString()));
buffer = new StringBuilder();
indexSequence = true;
break;
default:
buffer.append(current);
break;
}
if (current == ']') {
break;
}
current = chars[++i];
}
}
if (buffer.length() > 0) {
numbers.add(Integer.parseInt(buffer.toString()));
}
singleIndex = (numbers.size() == 1) && !sliceTo && !sliceFrom && !contextSize;
if (logger.isTraceEnabled()) {
logger.debug("numbers are : {}", numbers.toString());
logger.debug("sequence is singleNumber : {}", singleIndex);
logger.debug("sequence is numberSequence : {}", indexSequence);
logger.debug("sequence is sliceFrom : {}", sliceFrom);
logger.debug("sequence is sliceTo : {}", sliceTo);
logger.debug("sequence is sliceBetween : {}", sliceBetween);
logger.debug("sequence is contextFetch : {}", contextSize);
logger.debug("---------------------------------------------");
}
ArrayPathToken.Operation operation = null;
if (singleIndex) operation = ArrayPathToken.Operation.SINGLE_INDEX;
else if (indexSequence) operation = ArrayPathToken.Operation.INDEX_SEQUENCE;
else if (sliceFrom) operation = ArrayPathToken.Operation.SLICE_FROM;
else if (sliceTo) operation = ArrayPathToken.Operation.SLICE_TO;
else if (sliceBetween) operation = ArrayPathToken.Operation.SLICE_BETWEEN;
else if (contextSize) operation = ArrayPathToken.Operation.CONTEXT_SIZE;
assert operation != null;
return new ArrayPathToken(numbers, operation);
}
}
}

108
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathToken.java

@ -0,0 +1,108 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
/**
*
*/
abstract class PathToken {
private PathToken next;
private Boolean definite = null;
PathToken appendTailToken(PathToken next) {
this.next = next;
return next;
}
void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, String property) {
String evalPath = currentPath + "['" + property + "']";
Object propertyVal = readObjectProperty(property, model, ctx);
if (isLeaf()) {
ctx.addResult(evalPath, propertyVal);
} else {
next().evaluate(evalPath, propertyVal, ctx);
}
}
private Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) {
if (ctx.options().contains(Option.THROW_ON_MISSING_PROPERTY) && !ctx.jsonProvider().getPropertyKeys(model).contains(property)) {
throw new PathNotFoundException("Path [" + property + "] not found in the current context:\n" + ctx.jsonProvider().toJson(model));
}
return ctx.jsonProvider().getProperty(model, property);
}
void handleArrayIndex(int index, String currentPath, Object json, EvaluationContextImpl ctx) {
String evalPath = currentPath + "[" + index + "]";
Object evalHit = ctx.jsonProvider().getProperty(json, index);
if (isLeaf()) {
ctx.addResult(evalPath, evalHit);
} else {
next().evaluate(evalPath, evalHit, ctx);
}
}
PathToken next() {
if (isLeaf()) {
throw new IllegalStateException("Current path token is a leaf");
}
return next;
}
boolean isLeaf() {
return next == null;
}
public int getTokenCount() {
int cnt = 1;
PathToken token = this;
while (!token.isLeaf()){
token = token.next();
cnt++;
}
return cnt;
}
public boolean isPathDefinite() {
if(definite != null){
return definite.booleanValue();
}
boolean isDefinite = isTokenDefinite();
if (isDefinite && !isLeaf()) {
isDefinite = next.isPathDefinite();
}
definite = isDefinite;
return isDefinite;
}
@Override
public String toString() {
if (isLeaf()) {
return getPathFragment();
} else {
return getPathFragment() + next().toString();
}
}
@Override
public int hashCode() {
return toString().hashCode();
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
abstract void evaluate(String currentPath, Object model, EvaluationContextImpl ctx);
abstract boolean isTokenDefinite();
abstract String getPathFragment();
}

41
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PropertyPathToken.java

@ -0,0 +1,41 @@
package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.PathNotFoundException;
/**
*
*/
class PropertyPathToken extends PathToken {
private final String property;
public PropertyPathToken(String property) {
this.property = property;
}
public String getProperty() {
return property;
}
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (!ctx.jsonProvider().isMap(model)) {
throw new PathNotFoundException("Property " + currentPath + " not found!");
}
handleObjectProperty(currentPath, model, ctx, property);
}
@Override
boolean isTokenDefinite() {
return true;
}
@Override
public String getPathFragment() {
return new StringBuilder()
.append("['")
.append(property)
.append("']").toString();
}
}

66
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/RootPathToken.java

@ -0,0 +1,66 @@
package com.jayway.jsonpath.internal.spi.compiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
class RootPathToken extends PathToken /*implements Path*/ {
private static final Logger logger = LoggerFactory.getLogger(RootPathToken.class);
private PathToken tail;
private int tokenCount;
public RootPathToken() {
this.tail = this;
this.tokenCount = 1;
}
@Override
public int getTokenCount() {
return tokenCount;
}
public RootPathToken append(PathToken next) {
this.tail = tail.appendTailToken(next);
this.tokenCount++;
return this;
}
/*
@Override
public EvaluationContextImpl evaluate(Object model, Configuration configuration) {
if(logger.isDebugEnabled()) {
logger.debug("Evaluating path: {}", toString());
}
EvaluationContextImpl ctx = new EvaluationContextImpl(configuration, isDefinite());
evaluate("", model, ctx);
if(logger.isDebugEnabled()) {
logger.debug("Found:\n{}", JsonFormatter.prettyPrint(ctx.configuration().getProvider().toJson(ctx.getPathList())));
}
return ctx;
}
*/
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (isLeaf()) {
ctx.addResult("$", model);
} else {
next().evaluate("$", model, ctx);
}
}
@Override
public String getPathFragment() {
return "$";
}
@Override
boolean isTokenDefinite() {
return true;
}
}

175
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ScanPathToken.java

@ -0,0 +1,175 @@
package com.jayway.jsonpath.internal.spi.compiler;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
*
*/
class ScanPathToken extends PathToken {
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (isLeaf()) {
ctx.addResult(currentPath, model);
}
Predicate predicate = createScanPredicate(next(), ctx);
Map<String, Object> predicateMatches = new LinkedHashMap<String, Object>();
walk(currentPath, model, ctx, predicate, predicateMatches);
//Filters has already been evaluated
PathToken next = next();
if (next instanceof FilterPathToken) {
if (next.isLeaf()) {
for (Map.Entry<String, Object> match : predicateMatches.entrySet()) {
ctx.addResult(match.getKey(), match.getValue());
}
return;
} else {
next = next.next();
}
}
for (Map.Entry<String, Object> match : predicateMatches.entrySet()) {
next.evaluate(match.getKey(), match.getValue(), ctx);
}
}
public void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (ctx.jsonProvider().isMap(model)) {
walkObject(currentPath, model, ctx, predicate, predicateMatches);
} else if (ctx.jsonProvider().isArray(model)) {
walkArray(currentPath, model, ctx, predicate, predicateMatches);
}
}
public void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (predicate.matches(model)) {
predicateMatches.put(currentPath, model);
}
Iterable<Object> models = ctx.jsonProvider().toIterable(model);
int idx = 0;
for (Object evalModel : models) {
String evalPath = currentPath + "[" + idx + "]";
if (predicate.clazz().equals(FilterPathToken.class)) {
if (predicate.matches(evalModel)) {
predicateMatches.put(evalPath, evalModel);
}
}
walk(evalPath, evalModel, ctx, predicate, predicateMatches);
idx++;
}
}
public void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (predicate.matches(model)) {
predicateMatches.put(currentPath, model);
}
Collection<String> properties = ctx.jsonProvider().getPropertyKeys(model);
for (String property : properties) {
String evalPath = currentPath + "['" + property + "']";
Object propertyModel = ctx.jsonProvider().getProperty(model, property);
walk(evalPath, propertyModel, ctx, predicate, predicateMatches);
}
}
private Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) {
if (target instanceof PropertyPathToken) {
return new Predicate() {
private PropertyPathToken propertyPathToken = (PropertyPathToken) target;
@Override
public Class<?> clazz() {
return PropertyPathToken.class;
}
@Override
public boolean matches(Object model) {
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.contains(propertyPathToken.getProperty());
}
};
} else if (target instanceof ArrayPathToken) {
return new Predicate() {
@Override
public Class<?> clazz() {
return ArrayPathToken.class;
}
@Override
public boolean matches(Object model) {
return ctx.jsonProvider().isArray(model);
}
};
} else if (target instanceof WildcardPathToken) {
return new Predicate() {
@Override
public Class<?> clazz() {
return WildcardPathToken.class;
}
@Override
public boolean matches(Object model) {
return true;
}
};
} else if (target instanceof FilterPathToken) {
return new Predicate() {
private FilterPathToken filterPathToken = (FilterPathToken) target;
@Override
public Class<?> clazz() {
return FilterPathToken.class;
}
@Override
public boolean matches(Object model) {
return filterPathToken.accept(model, ctx.configuration());
}
};
} else {
return new Predicate() {
@Override
public Class<?> clazz() {
return null;
}
@Override
public boolean matches(Object model) {
return false;
}
};
}
}
@Override
boolean isTokenDefinite() {
return false;
}
@Override
public String getPathFragment() {
return "..";
}
private interface Predicate {
Class<?> clazz();
boolean matches(Object model);
}
}

31
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/WildcardPathToken.java

@ -0,0 +1,31 @@
package com.jayway.jsonpath.internal.spi.compiler;
/**
*
*/
class WildcardPathToken extends PathToken {
@Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (ctx.jsonProvider().isMap(model)) {
for (String property : ctx.jsonProvider().getPropertyKeys(model)) {
handleObjectProperty(currentPath, model, ctx, property);
}
} else if (ctx.jsonProvider().isArray(model)) {
for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) {
handleArrayIndex(idx, currentPath, model, ctx);
}
}
}
@Override
boolean isTokenDefinite() {
return false;
}
@Override
public String getPathFragment() {
return "[*]";
}
}

18
json-path/src/main/java/com/jayway/jsonpath/spi/impl/AbstractJsonProvider.java → json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi.impl;
package com.jayway.jsonpath.internal.spi.json;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import java.io.Serializable;
import java.util.ArrayList;
@ -80,8 +80,14 @@ public abstract class AbstractJsonProvider implements JsonProvider {
if (isMap(obj))
((Map) obj).put(key.toString(), value);
else {
int index = key instanceof Integer? (Integer) key : Integer.parseInt(key.toString());
((List) obj).add(index, value);
List list = (List) obj;
int index;
if (key != null) {
index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());
} else {
index = list.size();
}
list.add(index, value);
}
}
@ -110,14 +116,14 @@ public abstract class AbstractJsonProvider implements JsonProvider {
keys.add(String.valueOf(i));
}
return keys;
}
else{
} else {
return ((Map) obj).keySet();
}
}
/**
* Get the length of an array or object
*
* @param obj an array or an object
* @return the number of entries in the array or object
*/

35
json-path/src/main/java/com/jayway/jsonpath/spi/impl/JacksonProvider.java → json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonProvider.java

@ -12,25 +12,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi.impl;
package com.jayway.jsonpath.internal.spi.json;
import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.spi.MappingProvider;
import com.jayway.jsonpath.spi.Mode;
import com.jayway.jsonpath.spi.json.Mode;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.CollectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author Kalle Stenflo
*/
public class JacksonProvider extends AbstractJsonProvider implements MappingProvider{
public class JacksonProvider extends AbstractJsonProvider {
private static final Logger logger = LoggerFactory.getLogger(JacksonProvider.class);
private ObjectMapper objectMapper = new ObjectMapper();
@ -44,6 +49,7 @@ public class JacksonProvider extends AbstractJsonProvider implements MappingProv
try {
return objectMapper.readValue(json, Object.class);
} catch (IOException e) {
logger.debug("Invalid JSON: \n" + json);
throw new InvalidJsonException(e);
}
}
@ -89,22 +95,5 @@ public class JacksonProvider extends AbstractJsonProvider implements MappingProv
return new LinkedList<Object>();
}
//-------------------------------------------------------------------
//
// Mapping provider
//
//-------------------------------------------------------------------
@Override
public <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException {
return objectMapper.convertValue(fromValue, toValueType);
}
@Override
@SuppressWarnings({"unchecked"})
public <T extends Collection<E>, E> T convertValue(Object fromValue, Class<T> collectionType, Class<E> elementType) throws IllegalArgumentException {
CollectionType colType = objectMapper.getTypeFactory().constructCollectionType(collectionType, elementType);
return (T)objectMapper.convertValue(fromValue, colType);
}
}

8
json-path/src/main/java/com/jayway/jsonpath/spi/impl/JsonSmartJsonProvider.java → json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JsonSmartJsonProvider.java

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi.impl;
package com.jayway.jsonpath.internal.spi.json;
import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.spi.Mode;
import com.jayway.jsonpath.spi.json.Mode;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.ContainerFactory;
@ -35,7 +35,8 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider {
private Mode mode;
private ContainerFactory containerFactory = ContainerFactory.FACTORY_SIMPLE;
private ContainerFactory containerFactory = ContainerFactory.FACTORY_ORDERED;
//private ContainerFactory containerFactory = ContainerFactory.FACTORY_SIMPLE;
public JsonSmartJsonProvider() {
this(Mode.SLACK);
@ -55,7 +56,6 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider {
public Object parse(String json) {
try {
//return parser.parse(json, ContainerFactory.FACTORY_ORDERED);
return createParser().parse(json, containerFactory);
} catch (ParseException e) {
throw new InvalidJsonException(e);

29
json-path/src/main/java/com/jayway/jsonpath/spi/MappingProvider.java

@ -1,29 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.spi;
import java.util.Collection;
/**
* @author Kalle Stenflo
*/
public interface MappingProvider {
public <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException;
public <T extends Collection<E>, E> T convertValue(Object fromValue, Class<T> collectionType, Class<E> elementType) throws IllegalArgumentException;
}

54
json-path/src/main/java/com/jayway/jsonpath/spi/MappingProviderFactory.java

@ -1,54 +0,0 @@
/*
* Copyright 2011 the original author or authors.
* 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.jayway.jsonpath.spi;
import com.jayway.jsonpath.spi.impl.JacksonProvider;
/**
* @author Kalle Stenflo
*/
public abstract class MappingProviderFactory {
public static MappingProviderFactory factory = new MappingProviderFactory() {
private MappingProvider provider = null;
@Override
protected MappingProvider create() {
if (this.provider == null) {
synchronized (MappingProviderFactory.class) {
try {
Class.forName("org.codehaus.jackson.map.ObjectMapper");
provider = new JacksonProvider();
return provider;
} catch (ClassNotFoundException e) {
throw new RuntimeException("org.codehaus.jackson.map.ObjectMapper not found on classpath. This is an optional dependency needed for POJO conversions.", e);
}
}
} else {
return provider;
}
}
};
protected abstract MappingProvider create();
public static MappingProvider createProvider() {
return factory.create();
}
}

16
json-path/src/main/java/com/jayway/jsonpath/spi/compiler/EvaluationContext.java

@ -0,0 +1,16 @@
package com.jayway.jsonpath.spi.compiler;
import com.jayway.jsonpath.Configuration;
import java.util.List;
/**
*
*/
public interface EvaluationContext {
Configuration configuration();
<T> T get();
List<String> getPathList();
}

15
json-path/src/main/java/com/jayway/jsonpath/spi/compiler/Path.java

@ -0,0 +1,15 @@
package com.jayway.jsonpath.spi.compiler;
import com.jayway.jsonpath.Configuration;
/**
*
*/
public interface Path {
EvaluationContext evaluate(Object model, Configuration configuration);
boolean isDefinite();
int tokenCount();
}

4
json-path/src/main/java/com/jayway/jsonpath/spi/compiler/PathCompiler.java

@ -0,0 +1,4 @@
package com.jayway.jsonpath.spi.compiler;
public interface PathCompiler {
}

2
json-path/src/main/java/com/jayway/jsonpath/spi/HttpProvider.java → json-path/src/main/java/com/jayway/jsonpath/spi/http/HttpProvider.java

@ -1,4 +1,4 @@
package com.jayway.jsonpath.spi;
package com.jayway.jsonpath.spi.http;
import java.io.IOException;
import java.io.InputStream;

2
json-path/src/main/java/com/jayway/jsonpath/spi/HttpProviderFactory.java → json-path/src/main/java/com/jayway/jsonpath/spi/http/HttpProviderFactory.java

@ -1,4 +1,4 @@
package com.jayway.jsonpath.spi;
package com.jayway.jsonpath.spi.http;
import java.io.IOException;
import java.io.InputStream;

3
json-path/src/main/java/com/jayway/jsonpath/spi/JsonProvider.java → json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi;
package com.jayway.jsonpath.spi.json;
import com.jayway.jsonpath.InvalidJsonException;
@ -61,6 +61,7 @@ public interface JsonProvider {
/**
* Get the length of an array or object
*
* @param obj an array or an object
* @return the number of entries in the array or object
*/

6
json-path/src/main/java/com/jayway/jsonpath/spi/JsonProviderFactory.java → json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProviderFactory.java

@ -12,9 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi;
package com.jayway.jsonpath.spi.json;
import com.jayway.jsonpath.spi.impl.JsonSmartJsonProvider;
import com.jayway.jsonpath.internal.spi.json.JacksonProvider;
import com.jayway.jsonpath.internal.spi.json.JsonSmartJsonProvider;
/**
* @author Kalle Stenflo
@ -22,6 +23,7 @@ import com.jayway.jsonpath.spi.impl.JsonSmartJsonProvider;
public abstract class JsonProviderFactory {
private static JsonProvider provider = new JsonSmartJsonProvider();
//private static JsonProvider provider = new JacksonProvider();
public static JsonProvider createProvider() {
return provider;

2
json-path/src/main/java/com/jayway/jsonpath/spi/Mode.java → json-path/src/main/java/com/jayway/jsonpath/spi/json/Mode.java

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.spi;
package com.jayway.jsonpath.spi.json;
/**
* @author Kalle Stenflo

4
json-path/src/test/java/com/jayway/jsonpath/ArraySlicingTest.java

@ -76,8 +76,8 @@ public class ArraySlicingTest {
@Test
public void get_from_tail(){
Integer result = JsonPath.read(JSON_ARRAY, "$[3:]");
assertEquals(8, result.intValue());
List<Integer> result = JsonPath.read(JSON_ARRAY, "$[3:]");
assertThat(result, Matchers.contains(7, 8, 13, 20));
}
@Test

181
json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java

@ -25,12 +25,10 @@ public class ComplianceTest {
assertThat(JsonPath.<String>read(json, "$.a"), equalTo("a"));
assertThat(JsonPath.<List<String>>read(json, "$.*"), hasItems("a", "b", "e"));
assertThat(JsonPath.<List<String>>read(json, "$['*']"), hasItems("a", "b", "e"));
assertThat(JsonPath.<List<String>>read(json, "$[*]"), hasItems("a", "b", "e"));
assertThat(JsonPath.<String>read(json, "$['a']"), equalTo("a"));
//assertThat(JsonPath.<String>read(json, "$.'c d'"), is(equalTo("e"))); //low
//assertThat(JsonPath.<List<String>>read(json, "$[*]"), hasItems("a", "b", "e")); //low
assertThat(JsonPath.<String>read(json, "$.['c d']"), is(equalTo("e")));
assertThat(JsonPath.<List<String>>read(json, "$[*]"), hasItems("a", "b", "e"));
}
@Test
@ -71,183 +69,10 @@ public class ComplianceTest {
));
assertThat(JsonPath.<Integer>read(json, "$.points[4].x"), equalTo(0));
assertThat(JsonPath.<List<Integer>>read(json, "$.points[?(@.id == 'i4')].x"), hasItem(-6));
assertThat(JsonPath.<List<Integer>>read(json, "$.points[*].x"), hasItems(4, -2, 8, -6, 0, 1));
assertThat(JsonPath.<List<String>>read(json, "$.points[?(@.z)].id"), hasItems("i2", "i5"));
assertThat(JsonPath.<String>read(json, "$.points[(@.length - 1)].id"), equalTo("i6"));
//assertThat(JsonPath.<List<Integer>>read(json, "$['points'][?(@.x * @.x + @.y * @.y > 50)].id"), hasItems(?)); //low
}
@SuppressWarnings("UnusedAssignment")
@Test
public void test_four() throws Exception {
String json = "{ \"menu\": {\n" +
" \"header\": \"SVG Viewer\",\n" +
" \"items\": [\n" +
" {\"id\": \"Open\"},\n" +
" {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n" +
" null,\n" +
" {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n" +
" {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n" +
" {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n" +
" null,\n" +
" {\"id\": \"Quality\"},\n" +
" {\"id\": \"Pause\"},\n" +
" {\"id\": \"Mute\"},\n" +
" null,\n" +
" {\"id\": \"Find\", \"label\": \"Find...\"},\n" +
" {\"id\": \"FindAgain\", \"label\": \"Find Again\"},\n" +
" {\"id\": \"Copy\"},\n" +
" {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},\n" +
" {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},\n" +
" {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},\n" +
" {\"id\": \"ViewSource\", \"label\": \"View Source\"},\n" +
" {\"id\": \"SaveAs\", \"label\": \"Save As\"},\n" +
" null,\n" +
" {\"id\": \"Help\"},\n" +
" {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n" +
" ]\n" +
" }\n" +
" }";
//assertThat(JsonPath.<List<String>>read(json, "$.menu.items[?(@ && @.id && !@.label)].id"), hasItems("?")); //low
//assertThat(JsonPath.<List<String>>read(json, "$.menu.items[?(@ && @.label && /SVG/.test(@.label))].id"), hasItems("?")); //low
//assertThat(JsonPath.<List<String>>read(json, "$.menu.items[?(!@)]"), hasItems("?")); //low
//assertThat(JsonPath.<List<String>>read(json, "$..[0]"), hasItems("?")); //low
}
/*
--one
{ "o": { a: "a",
b: "b",
"c d": "e"
},
"p": [ "$.a",
"$['a']",
"$.'c d'",
"$.*",
"$['*']" ,
"$[*]"
]
},
--two
{ "o": [ 1, "2", 3.14, true, null ],
"p": [ "$[0]",
"$[4]",
"$[*]",
"$[-1:]"
]
},
--three
{ "o": { points: [
{ id: "i1", x: 4, y: -5 },
{ id: "i2", x: -2, y: 2, z: 1 },
{ id: "i3", x: 8, y: 3 },
{ id: "i4", x: -6, y: -1 },
{ id: "i5", x: 0, y: 2, z: 1 },
{ id: "i6", x: 1, y: 4 }
]
},
"p": [ "$.points[1]",
"$.points[4].x",
"$.points[?(@.id=='i4')].x",
"$.points[*].x",
"$['points'][?(@.x*@.x+@.y*@.y > 50)].id",
"$.points[?(@.z)].id",
"$.points[(@.length-1)].id"
]
},
--four
{ "o": { "menu": {
"header": "SVG Viewer",
"items": [
{"id": "Open"},
{"id": "OpenNew", "label": "Open New"},
null,
{"id": "ZoomIn", "label": "Zoom In"},
{"id": "ZoomOut", "label": "Zoom Out"},
{"id": "OriginalView", "label": "Original View"},
null,
{"id": "Quality"},
{"id": "Pause"},
{"id": "Mute"},
null,
{"id": "Find", "label": "Find..."},
{"id": "FindAgain", "label": "Find Again"},
{"id": "Copy"},
{"id": "CopyAgain", "label": "Copy Again"},
{"id": "CopySVG", "label": "Copy SVG"},
{"id": "ViewSVG", "label": "View SVG"},
{"id": "ViewSource", "label": "View Source"},
{"id": "SaveAs", "label": "Save As"},
null,
{"id": "Help"},
{"id": "About", "label": "About Adobe CVG Viewer..."}
]
}
},
"p": [ "$.menu.items[?(@ && @.id && !@.label)].id",
"$.menu.items[?(@ && @.label && /SVG/.test(@.label))].id",
"$.menu.items[?(!@)]",
"$..[0]"
]
},
--five
{ "o": { a: [1,2,3,4],
b: [5,6,7,8]
},
"p": [ "$..[0]",
"$..[-1:]",
"$..[?(@%2==0)]"
]
},
{ "o": { lin: {color:"red", x:2, y:3},
cir: {color:"blue", x:5, y:2, r:1 },
arc: {color:"green", x:2, y:4, r:2, phi0:30, dphi:120 },
pnt: {x:0, y:7 }
},
"p": [ "$.'?(@.color)'.x",
"$['lin','cir'].color"
]
},
{ "o": { lin: {color:"red", x:2, y:3},
cir: {color:"blue", x:5, y:2, r:1 },
arc: {color:"green", x:2, y:4, r:2, phi0:30, dphi:120 },
pnt: {x:0, y:7 }
},
"p": [ "$.'?(@.color)'.x",
"$['lin','arc'].color"
]
},
{ "o": { text: [ "hello", "world2.0"] },
"p": [ "$.text[?(@.length > 5)]",
"$.text[?(@.charAt(0) == 'h')]"
]
},
{ "o": { a: { a:2, b:3 },
b: { a:4, b:5 },
c: { a: { a:6, b:7}, c:8}
},
"p": [ "$..a"
]
},
{ "o": { a: [ { a:5, '@':2, '$':3 }, // issue 7: resolved by escaping the '@' character
{ a:6, '@':3, '$':4 }, // in a JSONPath expression.
{ a:7, '@':4, '$':5 }
]
},
"p": [ "$.a[?(@['\\@']==3)]",
"$.a[?(@['$']==5)]"
]
}
*/
}

77
json-path/src/test/java/com/jayway/jsonpath/DeepScanTest.java

@ -0,0 +1,77 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import java.util.Collections;
import java.util.Set;
public class DeepScanTest {
private static final String DOCUMENT = "{\n" +
" \"store\":{\n" +
" \"book\":[\n" +
" {\n" +
" \"category\":\"reference\",\n" +
" \"author\":\"Nigel Rees\",\n" +
" \"title\":\"Sayings of the Century\",\n" +
" \"price\":8.95\n" +
" },\n" +
" {\n" +
" \"category\":\"fiction\",\n" +
" \"author\":\"Evelyn Waugh\",\n" +
" \"title\":\"Sword of Honour\",\n" +
" \"price\":12.99\n" +
" },\n" +
" {\n" +
" \"category\":\"fiction\",\n" +
" \"author\":\"J. R. R. Tolkien\",\n" +
" \"title\":\"The Lord of the Rings\",\n" +
" \"isbn\":\"0-395-19395-8\",\n" +
" \"price\":22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\":{\n" +
" \"color\":\"red\",\n" +
" \"price\":19.95\n" +
" }\n" +
" }\n" +
"}";
private static final JsonProvider prov = JsonProviderFactory.createProvider();
private static final Set<Option> opts = Collections.emptySet();
/*
@Test
public void correct_path() {
System.out.println(DOCUMENT);
System.out.println(PathEvaluator.evaluate("$.store..", DOCUMENT, prov, opts));
}
@Test
public void a_string_property_can_be_scanned_for() {
PathEvaluationResult result = PathEvaluator.evaluate("$.store..category", DOCUMENT, prov, opts);
assertThat(result.getPathList(), hasItems("$['store']['book'][0]['category']", "$['store']['book'][1]['category']", "$['store']['book'][2]['category']"));
assertThat(result.getResultList(), hasItems(
Matchers.<Object>is("reference"),
Matchers.<Object>is("fiction"),
Matchers.<Object>is("fiction")));
System.out.println(result.toString());
}
@Test
public void a_path_can_end_with_deep_scan() {
String json = "{\"items\":[1, 3, 5, 7, 8, 13, 20]}";
//System.out.println( JsonPath.read(json, "$.."));
System.out.println(PathEvaluator.evaluate("$..", json, prov, opts).toString());
}
*/
}

57
json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java

@ -1,20 +1,9 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.filter.eval.ExpressionEvaluator;
import org.codehaus.jackson.node.BigIntegerNode;
import org.junit.Ignore;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by IntelliJ IDEA.
@ -24,6 +13,8 @@ import static org.junit.Assert.assertTrue;
*/
public class ExpressionEvalTest {
private static final Logger logger = LoggerFactory.getLogger(ExpressionEvalTest.class);
public static final String DOCUMENT= "{\n" +
" \"characters\": [\n" +
" {\n" +
@ -64,11 +55,13 @@ public class ExpressionEvalTest {
" \"Your Highness\"\n" +
" ], \n" +
" \"name\": \"Leia Organa\", \n" +
" \"occupation\": \"Senator\", \n" +
" \"occupation\": \"Senator\" \n" +
" }\n" +
" ]\n" +
"}\n";
private static final JsonProvider jp = JsonProviderFactory.createProvider();
/*
@Test
public void long_eval() throws Exception {
@ -194,7 +187,8 @@ public class ExpressionEvalTest {
Object o = JsonPath.read(DOCUMENT, "$.characters[?(@.name == 'Luke Skywalker' && @.occupation == 'Farm boy')]");
assertEquals("[{\"occupation\":\"Farm boy\",\"name\":\"Luke Skywalker\",\"aliases\":[\"Nerf herder\"],\"offspring\":null}]", o.toString());
assertThat((String)JsonPath.read(o, "[0].name"), is("Luke Skywalker"));
assertThat((String)JsonPath.read(o, "[0].occupation"), is("Farm boy"));
}
@Test
@ -205,30 +199,37 @@ public class ExpressionEvalTest {
assertEquals("[]", o.toString());
o = JsonPath.read(DOCUMENT, "$.characters[?(@.name == 'Luke Skywalker' && @.occupation != 'City boy')]");
assertEquals("[{\"occupation\":\"Farm boy\",\"name\":\"Luke Skywalker\",\"aliases\":[\"Nerf herder\"],\"offspring\":null}]", o.toString());
assertThat((String)JsonPath.read(o, "[0].name"), is("Luke Skywalker"));
assertThat((String)JsonPath.read(o, "[0].occupation"), CoreMatchers.not("City boy"));
}
@Test
public void nulls_filter() {
List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?]", filter(where("offspring").exists(false)));
System.out.println(result);
assertEquals(1, result.size());
//List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring == null)]");
//List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?]", Filter.filter(Criteria.where("offspring").is(null)));
//assertEquals(2, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring == null)]");
assertEquals(1, result.size());
// result = JsonPath.read(DOCUMENT, "$.characters[?]", filter(where("offspring").exists(false)));
// System.out.println(result);
// assertEquals(1, result.size());
//
//
// result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring != null)]");
// assertEquals(3, result.size());
//
// result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring)]");
// assertEquals(4, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring != null)]");
assertEquals(3, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring)]");
assertEquals(4, result.size());
PathEvaluationResult res = PathEvaluator.evaluate("$.characters[?(@.offspring != null)]", DOCUMENT, JsonProviderFactory.createProvider(), Collections.EMPTY_SET, new Filter[0]);
logger.debug(res.toString());
}
*/
}

388
json-path/src/test/java/com/jayway/jsonpath/Filter2Test.java

@ -0,0 +1,388 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.Criteria2.*;
import static com.jayway.jsonpath.Filter2.filter;
import static org.assertj.core.api.Assertions.assertThat;
public class Filter2Test {
Configuration conf = Configuration.defaultConfiguration();
Object json = conf.getProvider().parse(
"{" +
" \"int-key\" : 1, " +
" \"long-key\" : 3000000000, " +
" \"double-key\" : 10.1, " +
" \"boolean-key\" : true, " +
" \"null-key\" : null, " +
" \"string-key\" : \"string\", " +
" \"string-key-empty\" : \"\", " +
" \"char-key\" : \"c\", " +
" \"arr-empty\" : [], " +
" \"int-arr\" : [0,1,2,3,4], " +
" \"string-arr\" : [\"a\",\"b\",\"c\",\"d\",\"e\"] " +
"}"
);
//----------------------------------------------------------------------------
//
// EQ
//
//----------------------------------------------------------------------------
@Test
public void int_eq_evals() {
assertThat(filter(where("int-key").eq(1)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-key").eq(666)).apply(json, conf)).isEqualTo(false);
}
@Test
public void long_eq_evals() {
assertThat(filter(where("long-key").eq(3000000000L)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("long-key").eq(666L)).apply(json, conf)).isEqualTo(false);
}
@Test
public void double_eq_evals() {
assertThat(filter(where("double-key").eq(10.1D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.10D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.11D)).apply(json, conf)).isEqualTo(false);
}
@Test
public void string_eq_evals() {
assertThat(filter(where("string-key").eq("string")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").eq("666")).apply(json, conf)).isEqualTo(false);
}
@Test
public void boolean_eq_evals() {
assertThat(filter(where("boolean-key").eq(true)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("boolean-key").eq(false)).apply(json, conf)).isEqualTo(false);
}
@Test
public void null_eq_evals() {
assertThat(filter(where("null-key").eq(null)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("null-key").eq("666")).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("string-key").eq(null)).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// NE
//
//----------------------------------------------------------------------------
@Test
public void int_ne_evals() {
assertThat(filter(where("int-key").ne(1)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").ne(666)).apply(json, conf)).isEqualTo(true);
}
@Test
public void long_ne_evals() {
assertThat(filter(where("long-key").ne(3000000000L)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("long-key").ne(666L)).apply(json, conf)).isEqualTo(true);
}
@Test
public void double_ne_evals() {
assertThat(filter(where("double-key").ne(10.1D)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.10D)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.11D)).apply(json, conf)).isEqualTo(true);
}
@Test
public void string_ne_evals() {
assertThat(filter(where("string-key").ne("string")).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("string-key").ne("666")).apply(json, conf)).isEqualTo(true);
}
@Test
public void boolean_ne_evals() {
assertThat(filter(where("boolean-key").ne(true)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("boolean-key").ne(false)).apply(json, conf)).isEqualTo(true);
}
@Test
public void null_ne_evals() {
assertThat(filter(where("null-key").ne(null)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("null-key").ne("666")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").ne(null)).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// LT
//
//----------------------------------------------------------------------------
@Test
public void int_lt_evals() {
assertThat(filter(where("int-key").lt(10)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-key").lt(0)).apply(json, conf)).isEqualTo(false);
}
@Test
public void long_lt_evals() {
assertThat(filter(where("long-key").lt(4000000000L)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("long-key").lt(666L)).apply(json, conf)).isEqualTo(false);
}
@Test
public void double_lt_evals() {
assertThat(filter(where("double-key").lt(100.1D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").lt(1.1D)).apply(json, conf)).isEqualTo(false);
}
@Test
public void string_lt_evals() {
assertThat(filter(where("char-key").lt("x")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("char-key").lt("a")).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// LTE
//
//----------------------------------------------------------------------------
@Test
public void int_lte_evals() {
assertThat(filter(where("int-key").lte(10)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-key").lte(1)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-key").lte(0)).apply(json, conf)).isEqualTo(false);
}
@Test
public void long_lte_evals() {
assertThat(filter(where("long-key").lte(4000000000L)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("long-key").lte(3000000000L)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("long-key").lte(666L)).apply(json, conf)).isEqualTo(false);
}
@Test
public void double_lte_evals() {
assertThat(filter(where("double-key").lte(100.1D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").lte(10.1D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").lte(1.1D)).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// GT
//
//----------------------------------------------------------------------------
@Test
public void int_gt_evals() {
assertThat(filter(where("int-key").gt(10)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").gt(0)).apply(json, conf)).isEqualTo(true);
}
@Test
public void long_gt_evals() {
assertThat(filter(where("long-key").gt(4000000000L)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("long-key").gt(666L)).apply(json, conf)).isEqualTo(true);
}
@Test
public void double_gt_evals() {
assertThat(filter(where("double-key").gt(100.1D)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("double-key").gt(1.1D)).apply(json, conf)).isEqualTo(true);
}
@Test
public void string_gt_evals() {
assertThat(filter(where("char-key").gt("x")).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("char-key").gt("a")).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// GTE
//
//----------------------------------------------------------------------------
@Test
public void int_gte_evals() {
assertThat(filter(where("int-key").gte(10)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").gte(1)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-key").gte(0)).apply(json, conf)).isEqualTo(true);
}
@Test
public void long_gte_evals() {
assertThat(filter(where("long-key").gte(4000000000L)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("long-key").gte(3000000000L)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("long-key").gte(666L)).apply(json, conf)).isEqualTo(true);
}
@Test
public void double_gte_evals() {
assertThat(filter(where("double-key").gte(100.1D)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("double-key").gte(10.1D)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("double-key").gte(1.1D)).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// Regex
//
//----------------------------------------------------------------------------
@Test
public void string_regex_evals() {
assertThat(filter(where("string-key").regex(Pattern.compile("^string$"))).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").regex(Pattern.compile("^tring$"))).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("null-key").regex(Pattern.compile("^string$"))).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").regex(Pattern.compile("^string$"))).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// IN
//
//----------------------------------------------------------------------------
@Test
public void string_in_evals() {
assertThat(filter(where("string-key").in("a", null, "string")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").in("a", null)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("null-key").in("a", null)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("null-key").in("a", "b")).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("string-arr").in("a")).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// NIN
//
//----------------------------------------------------------------------------
@Test
public void string_nin_evals() {
assertThat(filter(where("string-key").nin("a", null, "string")).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("string-key").nin("a", null)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("null-key").nin("a", null)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("null-key").nin("a", "b")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-arr").nin("a")).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// ALL
//
//----------------------------------------------------------------------------
@Test
public void int_all_evals() {
assertThat(filter(where("int-arr").all(0,1)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("int-arr").all(0,7)).apply(json, conf)).isEqualTo(false);
}
@Test
public void string_all_evals() {
assertThat(filter(where("string-arr").all("a","b")).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-arr").all("a","x")).apply(json, conf)).isEqualTo(false);
}
@Test
public void not_array_all_evals() {
assertThat(filter(where("string-key").all("a","b")).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// SIZE
//
//----------------------------------------------------------------------------
@Test
public void array_size_evals() {
assertThat(filter(where("string-arr").size(5)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-arr").size(7)).apply(json, conf)).isEqualTo(false);
}
@Test
public void string_size_evals() {
assertThat(filter(where("string-key").size(6)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").size(7)).apply(json, conf)).isEqualTo(false);
}
@Test
public void other_size_evals() {
assertThat(filter(where("int-key").size(6)).apply(json, conf)).isEqualTo(false);
}
@Test
public void null_size_evals() {
assertThat(filter(where("null-key").size(6)).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// EXISTS
//
//----------------------------------------------------------------------------
@Test
public void exists_evals() {
assertThat(filter(where("string-key").exists(true)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").exists(false)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("missing-key").exists(true)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("missing-key").exists(false)).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// TYPE
//
//----------------------------------------------------------------------------
@Test
public void type_evals() {
assertThat(filter(where("string-key").type(String.class)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key").type(Integer.class)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").type(String.class)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-key").type(Integer.class)).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("null-key").type(String.class)).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-arr").type(List.class)).apply(json, conf)).isEqualTo(true);
}
//----------------------------------------------------------------------------
//
// NOT_EMPTY
//
//----------------------------------------------------------------------------
@Test
public void not_empty_evals() {
assertThat(filter(where("string-key").notEmpty()).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("string-key-empty").notEmpty()).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("int-arr").notEmpty()).apply(json, conf)).isEqualTo(true);
assertThat(filter(where("arr-empty").notEmpty()).apply(json, conf)).isEqualTo(false);
assertThat(filter(where("null-key").notEmpty()).apply(json, conf)).isEqualTo(false);
}
//----------------------------------------------------------------------------
//
// MATCHES
//
//----------------------------------------------------------------------------
@Test
public void matches_evals() {
Predicate p = new Predicate() {
@Override
public boolean apply(Object target, Configuration configuration) {
Map<String, Object> t = (Map<String, Object>) target;
Object o = t.get("int-key");
Integer i = (Integer) o;
return i == 1;
}
};
assertThat(filter(where("string-key").eq("string").and("$").matches(p)).apply(json, conf)).isEqualTo(true);
}
}

279
json-path/src/test/java/com/jayway/jsonpath/FilterTest.java

@ -1,6 +1,7 @@
package com.jayway.jsonpath;
import org.junit.Ignore;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import org.junit.Test;
import java.util.Collections;
@ -9,10 +10,12 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
import static com.jayway.jsonpath.Criteria2.where;
import static com.jayway.jsonpath.Filter2.filter;
import static java.util.Arrays.asList;
import static junit.framework.Assert.*;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Created by IntelliJ IDEA.
@ -57,7 +60,9 @@ public class FilterTest {
" }\n" +
"}";
private static final JsonProvider jp = JsonProviderFactory.createProvider();
private static final Configuration conf = Configuration.defaultConfiguration();
//-------------------------------------------------
//
// Single filter tests
@ -69,10 +74,10 @@ public class FilterTest {
check.put("foo", "foo");
check.put("bar", null);
assertTrue(filter(where("bar").is(null)).accept(check));
assertTrue(filter(where("foo").is("foo")).accept(check));
assertFalse(filter(where("foo").is("xxx")).accept(check));
assertFalse(filter(where("bar").is("xxx")).accept(check));
assertTrue(filter(where("bar").is(null)).apply(check, conf));
assertTrue(filter(where("foo").is("foo")).apply(check, conf));
assertFalse(filter(where("foo").is("xxx")).apply(check, conf));
assertFalse(filter(where("bar").is("xxx")).apply(check, conf));
}
@Test
@ -81,10 +86,10 @@ public class FilterTest {
check.put("foo", "foo");
check.put("bar", null);
assertTrue(filter(where("foo").ne(null)).accept(check));
assertTrue(filter(where("foo").ne("not foo")).accept(check));
assertFalse(filter(where("foo").ne("foo")).accept(check));
assertFalse(filter(where("bar").ne(null)).accept(check));
assertTrue(filter(where("foo").ne(null)).apply(check, conf));
assertTrue(filter(where("foo").ne("not foo")).apply(check, conf));
assertFalse(filter(where("foo").ne("foo")).apply(check, conf));
assertFalse(filter(where("bar").ne(null)).apply(check, conf));
}
@Test
@ -93,10 +98,10 @@ public class FilterTest {
check.put("foo", 12.5D);
check.put("foo_null", null);
assertTrue(filter(where("foo").gt(12D)).accept(check));
assertFalse(filter(where("foo").gt(null)).accept(check));
assertFalse(filter(where("foo").gt(20D)).accept(check));
assertFalse(filter(where("foo_null").gt(20D)).accept(check));
assertTrue(filter(where("foo").gt(12D)).apply(check, conf));
assertFalse(filter(where("foo").gt(null)).apply(check, conf));
assertFalse(filter(where("foo").gt(20D)).apply(check, conf));
assertFalse(filter(where("foo_null").gt(20D)).apply(check, conf));
}
@Test
@ -105,11 +110,11 @@ public class FilterTest {
check.put("foo", 12.5D);
check.put("foo_null", null);
assertTrue(filter(where("foo").gte(12D)).accept(check));
assertTrue(filter(where("foo").gte(12.5D)).accept(check));
assertFalse(filter(where("foo").gte(null)).accept(check));
assertFalse(filter(where("foo").gte(20D)).accept(check));
assertFalse(filter(where("foo_null").gte(20D)).accept(check));
assertTrue(filter(where("foo").gte(12D)).apply(check, conf));
assertTrue(filter(where("foo").gte(12.5D)).apply(check, conf));
assertFalse(filter(where("foo").gte(null)).apply(check, conf));
assertFalse(filter(where("foo").gte(20D)).apply(check, conf));
assertFalse(filter(where("foo_null").gte(20D)).apply(check, conf));
}
@Test
@ -118,10 +123,10 @@ public class FilterTest {
check.put("foo", 10.5D);
check.put("foo_null", null);
assertTrue(filter(where("foo").lt(12D)).accept(check));
assertFalse(filter(where("foo").lt(null)).accept(check));
assertFalse(filter(where("foo").lt(5D)).accept(check));
assertFalse(filter(where("foo_null").lt(5D)).accept(check));
//assertTrue(filter(where("foo").lt(12D)).apply(check, conf));
assertFalse(filter(where("foo").lt(null)).apply(check, conf));
//assertFalse(filter(where("foo").lt(5D)).apply(check, conf));
//assertFalse(filter(where("foo_null").lt(5D)).apply(check, conf));
}
@Test
@ -130,10 +135,10 @@ public class FilterTest {
check.put("foo", 12.5D);
check.put("foo_null", null);
assertTrue(filter(where("foo").lte(13D)).accept(check));
assertFalse(filter(where("foo").lte(null)).accept(check));
assertFalse(filter(where("foo").lte(5D)).accept(check));
assertFalse(filter(where("foo_null").lte(5D)).accept(check));
assertTrue(filter(where("foo").lte(13D)).apply(check, conf));
assertFalse(filter(where("foo").lte(null)).apply(check, conf));
assertFalse(filter(where("foo").lte(5D)).apply(check, conf));
assertFalse(filter(where("foo_null").lte(5D)).apply(check, conf));
}
@Test
@ -142,15 +147,15 @@ public class FilterTest {
check.put("item", 3);
check.put("null_item", null);
assertTrue(filter(where("item").in(1, 2, 3)).accept(check));
assertTrue(filter(where("item").in(asList(1, 2, 3))).accept(check));
assertFalse(filter(where("item").in(4, 5, 6)).accept(check));
assertFalse(filter(where("item").in(asList(4, 5, 6))).accept(check));
assertFalse(filter(where("item").in(asList('A'))).accept(check));
assertFalse(filter(where("item").in(asList((Object) null))).accept(check));
assertTrue(filter(where("item").in(1, 2, 3)).apply(check, conf));
assertTrue(filter(where("item").in(asList(1, 2, 3))).apply(check, conf));
assertFalse(filter(where("item").in(4, 5, 6)).apply(check, conf));
assertFalse(filter(where("item").in(asList(4, 5, 6))).apply(check, conf));
assertFalse(filter(where("item").in(asList('A'))).apply(check, conf));
assertFalse(filter(where("item").in(asList((Object) null))).apply(check, conf));
assertTrue(filter(where("null_item").in((Object) null)).accept(check));
assertFalse(filter(where("null_item").in(1, 2, 3)).accept(check));
assertTrue(filter(where("null_item").in((Object) null)).apply(check, conf));
assertFalse(filter(where("null_item").in(1, 2, 3)).apply(check, conf));
}
@Test
@ -159,14 +164,14 @@ public class FilterTest {
check.put("item", 3);
check.put("null_item", null);
assertTrue(filter(where("item").nin(4, 5)).accept(check));
assertTrue(filter(where("item").nin(asList(4, 5))).accept(check));
assertTrue(filter(where("item").nin(asList('A'))).accept(check));
assertTrue(filter(where("null_item").nin(1, 2, 3)).accept(check));
assertTrue(filter(where("item").nin(asList((Object) null))).accept(check));
assertTrue(filter(where("item").nin(4, 5)).apply(check, conf));
assertTrue(filter(where("item").nin(asList(4, 5))).apply(check, conf));
assertTrue(filter(where("item").nin(asList('A'))).apply(check, conf));
assertTrue(filter(where("null_item").nin(1, 2, 3)).apply(check, conf));
assertTrue(filter(where("item").nin(asList((Object) null))).apply(check, conf));
assertFalse(filter(where("item").nin(3)).accept(check));
assertFalse(filter(where("item").nin(asList(3))).accept(check));
assertFalse(filter(where("item").nin(3)).apply(check, conf));
assertFalse(filter(where("item").nin(asList(3))).apply(check, conf));
}
@Test
@ -174,8 +179,8 @@ public class FilterTest {
Map<String, Object> check = new HashMap<String, Object>();
check.put("items", asList(1, 2, 3));
assertTrue(filter(where("items").all(1, 2, 3)).accept(check));
assertFalse(filter(where("items").all(1, 2, 3, 4)).accept(check));
assertTrue(filter(where("items").all(1, 2, 3)).apply(check, conf));
assertFalse(filter(where("items").all(1, 2, 3, 4)).apply(check, conf));
}
@Test
@ -184,9 +189,9 @@ public class FilterTest {
check.put("items", asList(1, 2, 3));
check.put("items_empty", Collections.emptyList());
assertTrue(filter(where("items").size(3)).accept(check));
assertTrue(filter(where("items_empty").size(0)).accept(check));
assertFalse(filter(where("items").size(2)).accept(check));
assertTrue(filter(where("items").size(3)).apply(check, conf));
assertTrue(filter(where("items_empty").size(0)).apply(check, conf));
assertFalse(filter(where("items").size(2)).apply(check, conf));
}
@Test
@ -196,14 +201,14 @@ public class FilterTest {
check.put("foo", "foo");
check.put("foo_null", null);
assertTrue(filter(where("foo").exists(true)).accept(check));
assertFalse(filter(where("foo").exists(false)).accept(check));
assertTrue(filter(where("foo").exists(true)).apply(check, conf));
assertFalse(filter(where("foo").exists(false)).apply(check, conf));
assertTrue(filter(where("foo_null").exists(true)).accept(check));
assertFalse(filter(where("foo_null").exists(false)).accept(check));
assertTrue(filter(where("foo_null").exists(true)).apply(check, conf));
assertFalse(filter(where("foo_null").exists(false)).apply(check, conf));
assertTrue(filter(where("bar").exists(false)).accept(check, Configuration.defaultConfiguration()));
assertFalse(filter(where("bar").exists(true)).accept(check));
assertTrue(filter(where("bar").exists(false)).apply(check, conf));
assertFalse(filter(where("bar").exists(true)).apply(check, conf));
}
@Test
@ -215,18 +220,18 @@ public class FilterTest {
check.put("long", 1L);
check.put("double", 1.12D);
assertFalse(filter(where("string_null").type(String.class)).accept(check));
assertTrue(filter(where("string").type(String.class)).accept(check));
assertFalse(filter(where("string").type(Number.class)).accept(check));
assertFalse(filter(where("string_null").type(String.class)).apply(check, conf));
assertTrue(filter(where("string").type(String.class)).apply(check, conf));
assertFalse(filter(where("string").type(Number.class)).apply(check, conf));
assertTrue(filter(where("int").type(Integer.class)).accept(check));
assertFalse(filter(where("int").type(Long.class)).accept(check));
assertTrue(filter(where("int").type(Integer.class)).apply(check, conf));
assertFalse(filter(where("int").type(Long.class)).apply(check, conf));
assertTrue(filter(where("long").type(Long.class)).accept(check));
assertFalse(filter(where("long").type(Integer.class)).accept(check));
assertTrue(filter(where("long").type(Long.class)).apply(check, conf));
assertFalse(filter(where("long").type(Integer.class)).apply(check, conf));
assertTrue(filter(where("double").type(Double.class)).accept(check));
assertFalse(filter(where("double").type(Integer.class)).accept(check));
assertTrue(filter(where("double").type(Double.class)).apply(check, conf));
assertFalse(filter(where("double").type(Integer.class)).apply(check, conf));
}
@Test
@ -235,12 +240,55 @@ public class FilterTest {
check.put("name", "kalle");
check.put("name_null", null);
assertFalse(filter(where("name_null").regex(Pattern.compile(".alle"))).apply(check, conf));
assertTrue(filter(where("name").regex(Pattern.compile(".alle"))).apply(check, conf));
assertFalse(filter(where("name").regex(Pattern.compile("KALLE"))).apply(check, conf));
assertTrue(filter(where("name").regex(Pattern.compile("KALLE", Pattern.CASE_INSENSITIVE))).apply(check, conf));
}
@Test
public void combine_filter_deep_criteria() {
String json = "[\n" +
" {\n" +
" \"first-name\" : \"John\",\n" +
" \"last-name\" : \"Irving\",\n" +
" \"address\" : {\"state\" : \"Texas\"}\n" +
" },\n" +
" {\n" +
" \"first-name\" : \"Jock\",\n" +
" \"last-name\" : \"Ewing\",\n" +
" \"address\" : {\"state\" : \"Texas\"}\n" +
" },\n" +
" {\n" +
" \"first-name\" : \"Jock\",\n" +
" \"last-name\" : \"Barnes\",\n" +
" \"address\" : {\"state\" : \"Nevada\"}\n" +
" } \n" +
"]";
Filter2 filter = filter(
where("first-name").is("Jock")
.and("address.state").is("Texas"));
List<Map<String, Object>> jocksInTexas1 = JsonPath.read(json, "$[?]", filter);
List<Map<String, Object>> jocksInTexas2 = JsonPath.read(json, "$[?(@.first-name == 'Jock' && @.address.state == 'Texas')]");
JsonPath.parse(json).json();
assertThat((String)JsonPath.read(jocksInTexas1, "[0].address.state"), is("Texas"));
assertThat((String)JsonPath.read(jocksInTexas1, "[0].first-name"), is("Jock"));
assertThat((String)JsonPath.read(jocksInTexas1, "[0].last-name"), is("Ewing"));
assertFalse(filter(where("name_null").regex(Pattern.compile(".alle"))).accept(check));
assertTrue(filter(where("name").regex(Pattern.compile(".alle"))).accept(check));
assertFalse(filter(where("name").regex(Pattern.compile("KALLE"))).accept(check));
assertTrue(filter(where("name").regex(Pattern.compile("KALLE", Pattern.CASE_INSENSITIVE))).accept(check));
System.out.println("res1" + jocksInTexas1);
System.out.println("res2" + jocksInTexas2);
System.out.println("done");
}
//-------------------------------------------------
@ -259,11 +307,11 @@ public class FilterTest {
check.put("long", 1L);
check.put("double", 1.12D);
Filter shouldMarch = filter(where("string").is("foo").and("int").lt(11));
Filter shouldNotMarch = filter(where("string").is("foo").and("int").gt(11));
Filter2 shouldMarch = filter(where("string").is("foo").and("int").lt(11));
Filter2 shouldNotMarch = filter(where("string").is("foo").and("int").gt(11));
assertTrue(shouldMarch.accept(check));
assertFalse(shouldNotMarch.accept(check));
assertTrue(shouldMarch.apply(check, conf));
assertFalse(shouldNotMarch.apply(check, conf));
}
@Test
@ -276,13 +324,13 @@ public class FilterTest {
check.put("long", 1L);
check.put("double", 1.12D);
Filter filter = filter(where("string").is("foo").and("int").lt(11));
Filter2 filter = filter(where("string").is("foo").and("int").lt(11));
assertTrue(filter.accept(check));
assertTrue(filter.apply(check, conf));
filter.addCriteria(where("long").ne(1L));
assertFalse(filter.accept(check));
assertFalse(filter.apply(check, conf));
}
@ -296,23 +344,23 @@ public class FilterTest {
check.put("long", 1L);
check.put("double", 1.12D);
Filter filter = filter(where("string").is("foo"));
Filter2 filter = filter(where("string").is("foo"));
assertTrue(filter.accept(check));
assertTrue(filter.apply(check, conf));
Criteria criteria = where("string").is("not eq");
Criteria2 criteria = where("string").is("not eq");
filter.addCriteria(criteria);
assertFalse(filter.accept(check));
assertFalse(filter.apply(check, conf));
filter = filter(where("string").is("foo").and("string").is("not eq"));
assertFalse(filter.accept(check));
assertFalse(filter.apply(check, conf));
filter = filter(where("string").is("foo").and("string").is("foo"));
assertTrue(filter.accept(check));
assertTrue(filter.apply(check, conf));
}
@ -320,7 +368,7 @@ public class FilterTest {
@Test
public void arrays_of_maps_can_be_filtered() throws Exception {
/*
Map<String, Object> rootGrandChild_A = new HashMap<String, Object>();
rootGrandChild_A.put("name", "rootGrandChild_A");
@ -349,7 +397,7 @@ public class FilterTest {
Filter customFilter = new Filter.FilterAdapter<Map<String, Object>>() {
@Override
public boolean accept(Map<String, Object> map) {
public boolean apply(check, confMap<String, Object> map) {
if (map.get("name").equals("rootGrandChild_A")) {
return true;
}
@ -360,21 +408,25 @@ public class FilterTest {
Filter rootChildFilter = filter(where("name").regex(Pattern.compile("rootChild_[A|B]")));
Filter rootGrandChildFilter = filter(where("name").regex(Pattern.compile("rootGrandChild_[A|B]")));
List read = JsonPath.read(root, "children[?].children[?][?]", rootChildFilter, rootGrandChildFilter, customFilter);
//TODO: breaking v2 (solved by [?,?])
//List read = JsonPath.read(root, "children[?].children[?][?]", rootChildFilter, rootGrandChildFilter, customFilter);
List read = JsonPath.read(root, "children[?].children[?, ?]", rootChildFilter, rootGrandChildFilter, customFilter);
System.out.println(read.size());
*/
}
@Test
public void arrays_of_objects_can_be_filtered() throws Exception {
/*
Map<String, Object> doc = new HashMap<String, Object>();
doc.put("items", asList(1, 2, 3));
Filter customFilter = new Filter.FilterAdapter() {
@Override
public boolean accept(Object o, Configuration configuration) {
public boolean apply(check, confObject o, Configuration configuration) {
return 1 == (Integer) o;
}
};
@ -382,25 +434,29 @@ public class FilterTest {
List<Integer> res = JsonPath.read(doc, "$.items[?]", customFilter);
assertEquals(1, res.get(0).intValue());
*/
}
@Test
public void filters_can_contain_json_path_expressions() throws Exception {
Object doc = JsonModel.model(DOCUMENT).getJsonObject();
assertTrue(filter(where("$.store..price").gt(10)).accept(doc));
assertFalse(filter(where("$.store..price").gte(100)).accept(doc));
assertTrue(filter(where("$.store..category").ne("fiction")).accept(doc));
assertFalse(filter(where("$.store.bicycle.color").ne("red")).accept(doc));
assertTrue(filter(where("$.store.bicycle.color").ne("blue")).accept(doc));
assertTrue(filter(where("$.store..color").exists(true)).accept(doc));
assertTrue(filter(where("$.store..color").regex(Pattern.compile("^r.d$"))).accept(doc));
assertTrue(filter(where("$.store..color").type(String.class)).accept(doc));
assertTrue(filter(where("$.store..price").is(12.99)).accept(doc));
assertFalse(filter(where("$.store..price").is(13.99)).accept(doc));
assertFalse(filter(where("$.store..flavor").exists(true)).accept(doc));
System.out.println(DOCUMENT);
Object doc = JsonProviderFactory.createProvider().parse(DOCUMENT);
assertFalse(filter(where("$.store.bicycle.color").ne("red")).apply(doc, conf));
/*
assertFalse(filter(where("store..price").gt(10)).apply(doc, conf));
assertFalse(filter(where("$.store..price").gte(100)).apply(doc, conf));
assertTrue(filter(where("$.store..category").ne("fiction")).apply(doc, conf));
assertTrue(filter(where("$.store.bicycle.color").ne("blue")).apply(doc, conf));
assertTrue(filter(where("$.store..color").exists(true)).apply(doc, conf));
assertTrue(filter(where("$.store..color").regex(Pattern.compile("^r.d$"))).apply(doc, conf));
assertTrue(filter(where("$.store..color").type(String.class)).apply(doc, conf));
assertTrue(filter(where("$.store..price").is(12.99)).apply(doc, conf));
assertFalse(filter(where("$.store..price").is(13.99)).apply(doc, conf));
assertFalse(filter(where("$.store..flavor").exists(true)).apply(doc, conf));
*/
}
@Test
@ -427,33 +483,22 @@ public class FilterTest {
" ]\n" +
"}\n";
Object doc = JsonModel.model(json).getJsonObject();
Object doc = JsonProviderFactory.createProvider().parse(json);
List<Map<String, Object>> result = JsonPath.read(doc, "$.fields[?]", filter(where("errors").notEmpty()));
assertEquals(1, result.size());
System.out.println(result);
result = JsonPath.read(doc, "$.fields[?]", filter(where("name").notEmpty()));
assertEquals(2, result.size());
System.out.println(result);
List<Map<String, Object>> result2 = JsonPath.read(doc, "$.fields[?]", filter(where("name").notEmpty()));
assertEquals(2, result2.size());
System.out.println(result2);
}
@Test
public void collection_based_filters_cannot_be_applied_to_multi_level_expressions() {
@Test(expected = InvalidCriteriaException.class)
public void filter_path_must_be_absolute() {
try {
where("$.store.*").size(4);
fail("This should have thrown an exception");
} catch (IllegalArgumentException e) {
}
try {
where("$.store.*").in("foo");
fail("This should have thrown an exception");
} catch (IllegalArgumentException e) {
}
}
}

5
json-path/src/test/java/com/jayway/jsonpath/HttpProviderTest.java

@ -1,7 +1,8 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.spi.HttpProviderFactory;
import com.jayway.jsonpath.spi.http.HttpProviderFactory;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
@ -16,7 +17,7 @@ import static junit.framework.Assert.assertEquals;
* Date: 3/10/12
* Time: 8:12 AM
*/
//@Ignore
@Ignore
public class HttpProviderTest {

115
json-path/src/test/java/com/jayway/jsonpath/IssuesTest.java

@ -1,8 +1,8 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.Utils;
import net.minidev.json.JSONObject;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import org.hamcrest.Matchers;
import org.junit.Test;
@ -10,9 +10,8 @@ import java.io.InputStream;
import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
@ -23,6 +22,7 @@ import static org.junit.Assert.assertThat;
*/
public class IssuesTest {
private static final JsonProvider jp = JsonProviderFactory.createProvider();
@Test
public void issue_36() {
@ -37,22 +37,23 @@ public class IssuesTest {
Object o1 = JsonPath.read(json, "$.arrayOfObjectsAndArrays..k ");
Object o2 = JsonPath.read(json, "$.arrayOfObjects..k ");
assertEquals("[[\"json\"],[\"path\"],[\"is\"],[\"cool\"]]", o1.toString());
assertEquals("[\"json\",\"path\",\"is\",\"cool\"]", o2.toString());
assertEquals("[[\"json\"],[\"path\"],[\"is\"],[\"cool\"]]", jp.toJson(o1));
assertEquals("[\"json\",\"path\",\"is\",\"cool\"]", jp.toJson(o2));
}
@Test(expected = PathNotFoundException.class)
@Test
public void issue_11() throws Exception {
String json = "{ \"foo\" : [] }";
List<String> result = JsonPath.read(json, "$.foo[?(@.rel= 'item')][0].uri");
System.out.println(JsonPath.compile("$.foo[?(@.rel= 'item')][0].uri").isPathDefinite());
System.out.println(JsonPath.compile("$.foo[?(@.rel= 'item')][0]").isPathDefinite());
System.out.println(JsonPath.compile("$.foo[?(@.rel= 'item')]").isPathDefinite());
List<String> result = JsonPath.read(json, "$.foo[?(@.rel == 'item')][0].uri");
assertTrue(result.isEmpty());
}
@Test(expected = PathNotFoundException.class)
public void issue_11b() throws Exception {
String json = "{ \"foo\" : [] }";
JsonPath.read(json, "$.foo[0].uri");
}
@Test
public void issue_15() throws Exception {
String json = "{ \"store\": {\n" +
@ -122,6 +123,71 @@ public class IssuesTest {
assertEquals(1, result.size());
}
@Test
public void issue_37() {
String json = "[\n" +
" {\n" +
" \"id\": \"9\",\n" +
" \"sku\": \"SKU-001\",\n" +
" \"compatible\": false\n" +
" },\n" +
" {\n" +
" \"id\": \"13\",\n" +
" \"sku\": \"SKU-005\",\n" +
" \"compatible\": true\n" +
" },\n" +
" {\n" +
" \"id\": \"11\",\n" +
" \"sku\": \"SKU-003\",\n" +
" \"compatible\": true\n" +
" }\n" +
"]";
List<Double> result = JsonPath.read(json, "$.[?(@.compatible == true)].sku");
System.out.println(result);
//assertThat(result.get(0), is(new Double(10.1)));
//assertThat(result.get(1), is(new Double(21.0)));
}
@Test
public void issue_38() {
String json = "{\n" +
" \"datapoints\":[\n" +
" [\n" +
" 10.1,\n" +
" 13.0\n" +
" ],\n" +
" [\n" +
" 21.0,\n" +
" 22.0\n" +
" ]\n" +
" ]\n" +
"}";
List<Double> result = JsonPath.read(json, "$.datapoints.[*].[0]");
assertThat(result.get(0), is(new Double(10.1)));
assertThat(result.get(1), is(new Double(21.0)));
}
@Test
public void issue_39() {
String json = "{\n" +
" \"obj1\": {\n" +
" \"arr\": [\"1\", \"2\"]\n" +
" },\n" +
" \"obj2\": {\n" +
" \"arr\": [\"3\", \"4\"]\n" +
" }\n" +
"}\n";
List<String> result = JsonPath.read(json, "$..arr");
assertThat(result.size(), is(2));
}
@Test
public void issue_28_int() {
String json = "{\"contents\": [1,2,3]}";
@ -179,9 +245,10 @@ public class IssuesTest {
public void issue_29_a() throws Exception {
String json = "{\"list\": [ { \"a\":\"atext\", \"b.b-a\":\"batext2\", \"b\":{ \"b-a\":\"batext\", \"b-b\":\"bbtext\" } }, { \"a\":\"atext2\", \"b\":{ \"b-a\":\"batext2\", \"b-b\":\"bbtext2\" } } ] }";
List<JSONObject> result = JsonPath.read(json, "$.list[?(@['b.b-a']=='batext2')]");
List<Map<String, Object>> result = JsonPath.read(json, "$.list[?(@['b.b-a']=='batext2')]");
assertEquals(1, result.size());
assertEquals("atext", result.get(0).get("a"));
Object a = result.get(0).get("a");
assertEquals("atext", a);
result = JsonPath.read(json, "$.list[?(@.b.b-a=='batext2')]");
assertEquals(1, result.size());
@ -193,7 +260,7 @@ public class IssuesTest {
@Test
public void issue_29_b() throws Exception {
String json = "{\"list\": [ { \"a\":\"atext\", \"b\":{ \"b-a\":\"batext\", \"b-b\":\"bbtext\" } }, { \"a\":\"atext2\", \"b\":{ \"b-a\":\"batext2\", \"b-b\":\"bbtext2\" } } ] }";
List<String> result = JsonPath.read(json, "$.list[?]", Filter.filter(Criteria.where("b.b-a").eq("batext2")));
List<String> result = JsonPath.read(json, "$.list[?]", Filter2.filter(Criteria2.where("b.b-a").eq("batext2")));
assertTrue(result.size() == 1);
}
@ -243,4 +310,18 @@ public class IssuesTest {
}
@Test
public void array_root() {
String json = "[\n" +
" {\n" +
" \"a\": 1,\n" +
" \"b\": 2,\n" +
" \"c\": 3\n" +
" }\n" +
"]";
assertEquals(1, JsonPath.read(json, "$[0].a"));
}
}

101
json-path/src/test/java/com/jayway/jsonpath/JsonModelChainedCallsTest.java

@ -1,101 +0,0 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 3/14/12
* Time: 7:30 AM
*/
public class JsonModelChainedCallsTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"number\": 12,\n" +
" \"dot.notation\": \"new\"\n" +
" }\n" +
" }\n" +
"}";
@Test
public void convert_and_map() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Transformer<Map<String, Object>> transformer = new Transformer<Map<String, Object>>() {
public Object transform(Map<String, Object> map, Configuration configuration) {
map.remove("isbn");
map.put("author", "kalle");
return map;
}
};
Book book = model.opsForObject("store.book[0]").transform(transformer).to(Book.class);
assertEquals(book.author, "kalle");
}
@Test
public void convert_each_and_map() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Transformer<Object> transformer = new Transformer<Object>() {
public Object transform(Object obj, Configuration configuration) {
Map<String, Object> map = (Map<String, Object>) obj;
map.remove("isbn");
map.put("author", "kalle");
return map;
}
};
List<Book> books = model.opsForArray("store.book").each(transformer).toList().of(Book.class);
System.out.println();
}
public static class Book {
public String category;
public String author;
public String title;
public Double price;
}
}

143
json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java

@ -1,143 +0,0 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.util.List;
import java.util.Set;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
import static com.jayway.jsonpath.JsonModel.model;
import static junit.framework.Assert.assertEquals;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 3/4/12
* Time: 8:36 PM
*/
public class JsonModelMappingTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"dot.notation\": \"new\"\n" +
" }\n" +
" }\n" +
"}";
@Test
public void map_and_filter_can_be_combined() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Filter filter = Filter.filter(Criteria.where("category").is("fiction").and("price").gt(10D));
List<Book> books = model.map("$.store.book[?]", filter).toList().of(Book.class);
JsonPath jsonPath = JsonPath.compile("$.store.book[?]", filter(where("category").is("fiction").and("price").gt(10D)));
Object read = jsonPath.read(DOCUMENT);
List<Book> books1 = JsonModel.model(DOCUMENT).map("$.store.book[?]", filter).toListOf(Book.class);
model(DOCUMENT);
System.out.println("");
}
@Test
public void map_a_json_model_to_an_Class() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Book book = model.map("$.store.book[1]").to(Book.class);
assertEquals("fiction", book.category);
assertEquals("Evelyn Waugh", book.author);
assertEquals("Sword of Honour", book.title);
assertEquals(12.99D, book.price);
}
@Test
public void map_a_json_model_to_a_List() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
List<Book> booksList = model.map("$.store.book[0,1]").toListOf(Book.class);
assertEquals("fiction", booksList.get(1).category);
assertEquals("Evelyn Waugh", booksList.get(1).author);
assertEquals("Sword of Honour", booksList.get(1).title);
assertEquals(12.99D, booksList.get(1).price);
booksList = model.map("$.store.book[*]").toListOf(Book.class);
assertEquals("fiction", booksList.get(1).category);
assertEquals("Evelyn Waugh", booksList.get(1).author);
assertEquals("Sword of Honour", booksList.get(1).title);
assertEquals(12.99D, booksList.get(1).price);
booksList = model.map("$.store.book[*]").toList().of(Book.class);
assertEquals("fiction", booksList.get(1).category);
assertEquals("Evelyn Waugh", booksList.get(1).author);
assertEquals("Sword of Honour", booksList.get(1).title);
assertEquals(12.99D, booksList.get(1).price);
}
@Test
public void map_a_json_model_to_a_Set() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Set<Book> bookSet = model.map("$.store.book[1]").toSetOf(Book.class);
Book book = bookSet.iterator().next();
assertEquals("fiction", book.category);
assertEquals("Evelyn Waugh", book.author);
assertEquals("Sword of Honour", book.title);
assertEquals(12.99D, book.price);
}
public static class Book {
public String category;
public String author;
public String title;
public String isbn;
public Double price;
}
}

286
json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java

@ -1,286 +0,0 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.util.*;
import static com.jayway.jsonpath.JsonModel.model;
import static junit.framework.Assert.assertEquals;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 3/4/12
* Time: 4:55 PM
*/
public class JsonModelOpsTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"number\": 12,\n" +
" \"dot.notation\": \"new\"\n" +
" }\n" +
" }\n" +
"}";
@Test
public void convert_values() throws Exception {
JsonModel model = model(DOCUMENT).getSubModel("store.bicycle");
JsonModel.ObjectOps ops = model.opsForObject();
assertEquals(19.95D, ops.getDouble("price"));
assertEquals(new Long(12), ops.getLong("number"));
assertEquals(new Integer(12), ops.getInteger("number"));
int i = ops.getInteger("number");
long l = ops.getLong("number");
double d = ops.getDouble("price");
}
@Test
public void object_ops_can_update() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
model.opsForObject("store.book[0]")
.put("author", "Kalle")
.put("price", 12.30D);
assertEquals("Kalle", model.get("store.book[0].author"));
assertEquals(12.30D, model.get("store.book[0].price"));
}
@Test
public void array_ops_can_add_element() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Map<String, Object> newBook = new HashMap<String, Object>();
newBook.put("category", "reference");
newBook.put("author", "Kalle");
newBook.put("title", "JSONPath book");
newBook.put("isbn", "0-553-21311-34");
newBook.put("price", 12.10D);
model.opsForArray("store.book").add(newBook);
JsonModel subModel = model.getSubModel("store.book[4]");
assertEquals("reference", subModel.get("category"));
assertEquals("Kalle", subModel.get("author"));
assertEquals("JSONPath book", subModel.get("title"));
assertEquals("0-553-21311-34", subModel.get("isbn"));
assertEquals(12.10D, subModel.get("price"));
}
@Test
public void ops_can_transform_object_root() throws Exception {
Map<String, Object> rootDocument = new HashMap<String, Object>();
rootDocument.put("category", "reference");
rootDocument.put("author", "Kalle");
rootDocument.put("title", "JSONPath book");
rootDocument.put("isbn", "0-553-21311-34");
rootDocument.put("price", 12.10D);
JsonModel model = JsonModel.model(rootDocument);
model.opsForObject().transform(new Transformer<Map<String, Object>>() {
@Override
public Object transform(Map<String, Object> obj, Configuration configuration) {
obj.put("name", "kalle");
return obj;
}
});
assertEquals("kalle", model.get("name"));
}
@Test
public void ops_can_transform_array_root() throws Exception {
List<Object> rootDocument = new ArrayList<Object>();
rootDocument.add(Collections.singletonMap("name", "kalle"));
rootDocument.add(Collections.singletonMap("name", "bob"));
rootDocument.add(Collections.singletonMap("name", "zak"));
JsonModel model = JsonModel.model(rootDocument);
model.opsForArray().transform(new Transformer<List<Object>>() {
@Override
public Object transform(List<Object> obj, Configuration configuration) {
return Collections.singletonMap("root", "new");
}
});
assertEquals("new", model.get("root"));
}
@Test
public void ops_can_transform_nested_document() throws Exception {
Map<String, Object> childDocument = new HashMap<String, Object>();
childDocument.put("level", 1);
Map<String, Object> rootDocument = new HashMap<String, Object>();
rootDocument.put("category", "reference");
rootDocument.put("author", "Kalle");
rootDocument.put("title", "JSONPath book");
rootDocument.put("isbn", "0-553-21311-34");
rootDocument.put("price", 12.10D);
rootDocument.put("child", childDocument);
JsonModel model = JsonModel.model(rootDocument);
model.opsForObject("child").transform(new Transformer<Map<String, Object>>() {
@Override
public Object transform(Map<String, Object> obj, Configuration configuration) {
obj.put("name", "kalle");
return obj;
}
});
assertEquals("kalle", model.get("child.name"));
}
@Test
public void arrays_can_be_mapped() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
List<Book> books1 = model.opsForArray("store.book").toList().of(Book.class);
List<Book> books2 = model.opsForArray("store.book").toListOf(Book.class);
Set<Book> books3 = model.opsForArray("store.book").toSetOf(Book.class);
assertEquals(4, books1.size());
assertEquals(4, books2.size());
assertEquals(4, books3.size());
}
@Test
public void objects_can_be_mapped() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
Book book = model.opsForObject("store.book[1]").to(Book.class);
assertEquals("fiction", book.category);
assertEquals("Evelyn Waugh", book.author);
assertEquals("Sword of Honour", book.title);
assertEquals(12.99D, book.price);
}
@Test
public void object_can_be_transformed() throws Exception {
Transformer transformer = new Transformer<Map<String, Object>>() {
@Override
public Map<String, Object> transform(Map<String, Object> model, Configuration configuration) {
model.put("newProp", "newProp");
return model;
}
};
JsonModel model = JsonModel.model(DOCUMENT);
model.opsForObject("store.book[1]").transform(transformer);
assertEquals("newProp", model.get("store.book[1].newProp"));
}
@Test
public void arrays_can_be_transformed() throws Exception {
Transformer transformer = new Transformer<List<Object>>() {
@Override
public Object transform(List<Object> model, Configuration configuration) {
for (Object o : model) {
Map<String, Object> map = (Map<String, Object>) o;
map.put("newProp", "newProp");
}
return model;
}
};
JsonModel model = JsonModel.model(DOCUMENT);
model.opsForArray("store.book").transform(transformer);
assertEquals("newProp", model.get("store.book[1].newProp"));
}
@Test
public void array_can_be_transformed_to_primitives() throws Exception {
Transformer positionTransformer = new Transformer<List<Object>>() {
private int i = 0;
@Override
public Object transform(List<Object> model, Configuration configuration) {
List<Object> newList = new ArrayList<Object>();
for (Object o : model) {
newList.add(new Integer(i++));
}
return newList;
}
};
Transformer multiplyingTransformer = new Transformer<List<Object>>() {
@Override
public Object transform(List<Object> model, Configuration configuration) {
for (int i = 0; i < model.size(); i++) {
int curr = (Integer) model.get(i);
model.set(i, curr * 2);
}
return model;
}
};
JsonModel model = JsonModel.model(DOCUMENT);
model.opsForArray("store.book").transform(positionTransformer).transform(multiplyingTransformer);
assertEquals(2, model.get("store.book[1]"));
}
public static class Book {
public String category;
public String author;
public String title;
public String isbn;
public Double price;
}
}

116
json-path/src/test/java/com/jayway/jsonpath/JsonModelSubModelTest.java

@ -1,116 +0,0 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.util.Collections;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 3/11/12
* Time: 5:07 PM
*/
public class JsonModelSubModelTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"dot.notation\": \"new\",\n" +
" \"book\": { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
@Test(expected = IllegalArgumentException.class)
public void a_sub_model_path_must_be_definite() throws Exception {
JsonModel.model(DOCUMENT).getSubModel("$store.book[*]");
}
@Test
public void test_a_sub_model_can_be_fetched_and_read() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
assertEquals("Nigel Rees", model.getSubModel("$store.book[0]").get("author"));
assertEquals("Nigel Rees", model.getSubModel(JsonPath.compile("$store.book[0]")).get("author"));
}
@Test
public void when_a_sub_model_is_updated_the_master_model_is_updated() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
JsonModel subModel = model.getSubModel("store.book[0]");
subModel.opsForObject().put("author", "kalle");
assertEquals("kalle", model.get("store.book[0].author"));
}
@Test
public void when_a_sub_model_root_is_transformed_the_master_model_is_updated() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
JsonModel subModel = model.getSubModel("store.book[0]");
subModel.opsForObject().transform(new Transformer<Map<String, Object>>() {
@Override
public Object transform(Map<String, Object> obj, Configuration configuration) {
return Collections.singletonMap("prop", "new");
}
});
assertEquals("new", model.get("store.book[0].prop"));
}
@Test
public void when_a_sub_model_child_is_transformed_the_master_model_is_updated() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
JsonModel subModel = model.getSubModel("store.bicycle.book");
subModel.opsForObject().transform(new Transformer<Map<String, Object>>() {
@Override
public Object transform(Map<String, Object> obj, Configuration configuration) {
return Collections.singletonMap("prop", "new");
}
});
assertEquals("new", model.get("store.bicycle.book.prop"));
}
}

135
json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java

@ -1,135 +0,0 @@
package com.jayway.jsonpath;
import org.junit.Ignore;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static java.util.Arrays.asList;
import static junit.framework.Assert.*;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 11/8/11
* Time: 7:52 PM
*/
public class JsonModelTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"dot.notation\": \"new\"\n" +
" }\n" +
" }\n" +
"}";
public final static String INVALID_DOCUMENT = "{?\\?\\?!!?~q`}}}}}\"\" \"store\": {\n";
@Test(expected = InvalidJsonException.class)
public void invalid_json_throws() throws Exception {
JsonModel.model(INVALID_DOCUMENT).get("store.id");
}
@Test(expected = InvalidPathException.class)
public void invalid_path_throws() throws Exception {
JsonModel.model(DOCUMENT).get("a(");
}
@Test
public void a_model_can_be_pretty_printed() throws Exception {
JsonModel model = JsonModel.model(DOCUMENT);
model.print();
}
@Test
public void has_path_validates() throws Exception {
assertFalse(JsonModel.model(DOCUMENT).hasPath("store.invalid"));
assertFalse(JsonModel.model(DOCUMENT).hasPath("store.book[0].foo"));
assertTrue(JsonModel.model(DOCUMENT).hasPath("store.book"));
assertTrue(JsonModel.model(DOCUMENT).hasPath("store.book[0].title"));
}
@Test
public void a_json_document_can_be_fetched_with_a_URL() throws Exception {
URL url = new URL("http://maps.googleapis.com/maps/api/geocode/json");
assertEquals("REQUEST_DENIED", JsonModel.model(url).get("status"));
}
@Test
public void a_json_document_can_be_fetched_with_a_InputStream() throws Exception {
ByteArrayInputStream bis = new ByteArrayInputStream(DOCUMENT.getBytes());
assertEquals("Nigel Rees", JsonModel.model(bis).get("store.book[0].author"));
}
@Test
public void maps_and_list_can_queried() throws Exception {
Map<String, Object> doc = new HashMap<String, Object>();
doc.put("items", asList(0, 1, 2));
doc.put("child", Collections.singletonMap("key", "value"));
JsonModel model = JsonModel.model(doc);
assertEquals("value", model.get("$child.key"));
assertEquals(1, model.get("$items[1]"));
assertEquals("{\"child\":{\"key\":\"value\"},\"items\":[0,1,2]}", model.toJson());
}
@Test
public void query_for_null_property_returns_null() {
String documentWithNull =
"{ \"store\": {\n" +
" \"book\": { \n" +
" \"color\": null\n" +
" }\n" +
" }\n" +
"}";
Object color = JsonModel.model(documentWithNull).get("store.book.color");
assertNull(color);
}
@Test(expected = InvalidPathException.class)
public void query_for_property_on_array_throws() throws Exception {
JsonModel.model(DOCUMENT).get("store.book.color");
}
}

8
json-path/src/test/java/com/jayway/jsonpath/JsonPathFilterTest.java

@ -55,7 +55,7 @@ public class JsonPathFilterTest {
" }\n" +
"}";
/*
@Test
public void arrays_of_maps_can_be_filtered() throws Exception {
@ -104,8 +104,9 @@ public class JsonPathFilterTest {
List read = JsonPath.read(root, "children[?].children[?][?]", rootChildFilter, rootGrandChildFilter, customFilter);
//TODO: breaking v2 solved by [?,?]
//List read = JsonPath.read(root, "children[?].children[?][?]", rootChildFilter, rootGrandChildFilter, customFilter);
List read = JsonPath.read(root, "children[?].children[?, ?]", rootChildFilter, rootGrandChildFilter, customFilter);
System.out.println(read.size());
@ -129,4 +130,5 @@ public class JsonPathFilterTest {
assertEquals(1, res.get(0).intValue());
}
*/
}

34
json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java

@ -1,12 +1,14 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.spi.compiler.PathCompiler;
import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import com.jayway.jsonpath.util.ScriptEngineJsonPath;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.*;
@ -62,6 +64,8 @@ public class JsonPathTest {
" }\n" +
"}";
public final static Object OBJ_DOCUMENT = JsonProviderFactory.createProvider().parse(DOCUMENT);
private final static String PRODUCT_JSON = "{\n" +
"\t\"product\": [ {\n" +
@ -78,6 +82,16 @@ public class JsonPathTest {
private final static String ARRAY_EXPAND = "[{\"parent\": \"ONE\", \"child\": {\"name\": \"NAME_ONE\"}}, [{\"parent\": \"TWO\", \"child\": {\"name\": \"NAME_TWO\"}}]]";
@Test(expected = PathNotFoundException.class)
public void missing_prop() {
Object read = JsonPath.using(Configuration.defaultConfiguration().options(Option.THROW_ON_MISSING_PROPERTY)).parse(DOCUMENT).read("$.store.book[*].fooBar");
System.out.println(read);
}
@Test
public void bracket_notation_with_dots() {
String json = "{\n" +
@ -171,8 +185,8 @@ public class JsonPathTest {
@Test
public void read_path_with_colon() throws Exception {
assertEquals(JsonPath.read(DOCUMENT, "$.store.bicycle.foo:bar"), "fooBar");
//TODO: breaking v2
//assertEquals(JsonPath.read(DOCUMENT, "$.store.bicycle.foo:bar"), "fooBar");
assertEquals(JsonPath.read(DOCUMENT, "$['store']['bicycle']['foo:bar']"), "fooBar");
}
@ -219,10 +233,17 @@ public class JsonPathTest {
@Test
public void all_store_properties() throws Exception {
/*
List<Object> itemsInStore = JsonPath.read(DOCUMENT, "$.store.*");
assertEquals(JsonPath.read(itemsInStore, "$.[0].[0].author"), "Nigel Rees");
assertEquals(JsonPath.read(itemsInStore, "$.[0][0].author"), "Nigel Rees");
*/
List<String> result = PathCompiler.tokenize("$.store.*").evaluate(OBJ_DOCUMENT, Configuration.defaultConfiguration()).getPathList();
Assertions.assertThat(result).containsOnly(
"$['store']['bicycle']",
"$['store']['book']");
}
@Test
@ -234,9 +255,12 @@ public class JsonPathTest {
@Test
public void access_array_by_index_from_tail() throws Exception {
//TODO: breaking change
//assertThat(JsonPath.<String>read(DOCUMENT, "$..book[(@.length-1)].author"), equalTo("J. R. R. Tolkien"));
//assertThat(JsonPath.<String>read(DOCUMENT, "$..book[1:].author"), equalTo("J. R. R. Tolkien"));
assertThat(JsonPath.<String>read(DOCUMENT, "$..book[(@.length-1)].author"), equalTo("J. R. R. Tolkien"));
assertThat(JsonPath.<String>read(DOCUMENT, "$..book[1:].author"), equalTo("J. R. R. Tolkien"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[(@.length-1)].author"), hasItems("J. R. R. Tolkien"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[1:].author"), hasItems("Evelyn Waugh","Herman Melville","J. R. R. Tolkien"));
}
@Test

16
json-path/src/test/java/com/jayway/jsonpath/JsonProviderTest.java

@ -1,13 +1,8 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.spi.impl.JacksonProvider;
import com.jayway.jsonpath.internal.spi.json.JacksonProvider;
import org.junit.Test;
import java.io.Serializable;
import static com.jayway.jsonpath.JsonModel.model;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
@ -55,16 +50,7 @@ public class JsonProviderTest {
@Test
public void clone_test() throws Exception {
Serializable jsonObject = (Serializable) model(DOCUMENT).getJsonObject();
Object clone = Utils.clone(jsonObject);
System.out.println(model(clone).toJson());
}
@Test

20
json-path/src/test/java/com/jayway/jsonpath/MultiAttributeTest.java

@ -3,10 +3,8 @@ package com.jayway.jsonpath;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -53,22 +51,6 @@ public class MultiAttributeTest {
"}";
@Test
public void multiple_attributes_from_array_content(){
List<Map<String, Object>> matches = JsonPath.read(DOCUMENT, "$.store.book[*].['category', 'title']");
assertEquals(4, matches.size());
assertTrue(matches.get(1).containsKey("category"));
assertTrue(matches.get(1).containsKey("title"));
assertEquals(2, matches.get(1).size());
}
@Test
public void multiple_attributes_from_single_object(){
Map<String, Object> match = JsonPath.read(DOCUMENT, "$.store.bicycle['color', 'display-price']");
assertTrue(match.containsKey("color"));
assertTrue(match.containsKey("display-price"));
}
}

3
json-path/src/test/java/com/jayway/jsonpath/NullHandlingTest.java

@ -4,7 +4,6 @@ import org.hamcrest.Matchers;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
@ -41,7 +40,7 @@ public class NullHandlingTest {
@Test(expected = PathNotFoundException.class)
public void not_defined_property_throws_PathNotFoundException() {
assertNull(JsonPath.read(DOCUMENT, "$.children[0].child.age"));
JsonPath.read(DOCUMENT, "$.children[0].child.age");
}

156
json-path/src/test/java/com/jayway/jsonpath/PathTest.java

@ -1,156 +0,0 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.PathTokenizer;
import org.hamcrest.Matcher;
import org.junit.Test;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.*;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 2/2/11
* Time: 1:22 PM
*/
public class PathTest {
Filter filter = new Filter(){
@Override
public boolean accept(Object obj) {
return true;
}
@Override
public boolean accept(Object obj, Configuration configuration) {
return true;
}
@Override
public Filter addCriteria(Criteria criteria) {
return this;
}
};
@Test
public void path_is_not_definite() throws Exception {
assertFalse(JsonPath.compile("$..book[0]").isPathDefinite());
assertFalse(JsonPath.compile("$book[?]", filter).isPathDefinite());
assertFalse(JsonPath.compile("$.books[*]").isPathDefinite());
}
@Test
public void path_is_definite() throws Exception {
assertTrue(JsonPath.compile("$.definite.this.is").isPathDefinite());
assertTrue(JsonPath.compile("rows[0].id").isPathDefinite());
}
@Test
public void valid_path_is_split_correctly() throws Exception {
assertPath("$.store[*]", hasItems("$", "store", "[*]"));
assertPath("$", hasItems("$"));
assertPath("$..*", hasItems("$", "..", "*"));
assertPath("$.store", hasItems("$", "store"));
assertPath("$.store.*", hasItems("$", "store", "*"));
assertPath("$.store[*].name", hasItems("$", "store", "[*]", "name"));
assertPath("$..book[-1:].foo.bar", hasItems("$", "..", "book", "[-1:]", "foo", "bar"));
assertPath("$..book[?(@.isbn)]", hasItems("$", "..", "book", "[?(@.isbn)]"));
assertPath("['store'].['price']", hasItems("$", "store", "price"));
assertPath("$.['store'].['price']", hasItems("$", "store", "price"));
assertPath("$.['store']['price']", hasItems("$", "store", "price"));
assertPath("$.['store'].price", hasItems("$", "store", "price"));
assertPath("$.['store space']['price space']", hasItems("$", "store space", "price space"));
assertPath("$.['store']['nice.price']", hasItems("$", "store", "nice.price"));
assertPath("$..book[?(@.price<10)]", hasItems("$", "..", "book", "[?(@.price<10)]"));
assertPath("$..book[?(@.price<10)]", hasItems("$", "..", "book", "[?(@.price<10)]"));
assertPath("$.store.book[*].author", hasItems("$", "store", "book", "[*]", "author"));
assertPath("$.store..price", hasItems("$", "store", "..", "price"));
}
@Test
public void white_space_are_removed() throws Exception {
assertPath("$.[ 'store' ]", hasItems("$", "store"));
assertPath("$.[ 'store' ]", hasItems("$", "store"));
assertPath("$.['store bore']", hasItems("$", "store bore"));
assertPath("$..book[ ?(@.price<10) ]", hasItems("$", "..", "book", "[?(@.price<10)]"));
assertPath("$..book[?(@.price<10 )]", hasItems("$", "..", "book", "[?(@.price<10)]"));
assertPath("$..book[?( @.price<10)]", hasItems("$", "..", "book", "[?(@.price<10)]"));
assertPath("$..book[ ?(@.price<10)]", hasItems("$", "..", "book", "[?(@.price<10)]"));
}
@Test
public void dot_ending_ignored() throws Exception {
assertPath("$..book['something'].", hasItems("$", "..", "something"));
}
@Test
public void invalid_path_throws_exception() throws Exception {
assertPathInvalid("$...*");
}
@Test
public void multi_field_select(){
PathTokenizer tokenizer = new PathTokenizer("$.contents[*].['groupType', 'type']");
for (String fragment : tokenizer.getFragments()) {
System.out.println(fragment);
}
}
//----------------------------------------------------------------
//
// Helpers
//
//----------------------------------------------------------------
private void assertPathInvalid(String path) {
try {
PathTokenizer tokenizer = new PathTokenizer(path);
assertTrue("Expected exception!", false);
} catch (InvalidPathException expected) {}
}
private void assertPath(String path, Matcher<Iterable<String>> matcher) {
System.out.println("PATH: " + path);
PathTokenizer tokenizer = new PathTokenizer(path);
for (String fragment : tokenizer.getFragments()) {
System.out.println(fragment);
}
assertThat(tokenizer.getFragments(), matcher);
System.out.println("----------------------------------");
}
}

30
json-path/src/test/java/com/jayway/jsonpath/JsonModelSubModelDetachedTest.java → json-path/src/test/java/com/jayway/jsonpath/Runner.java

@ -1,16 +1,9 @@
package com.jayway.jsonpath;
import org.junit.Test;
import static com.jayway.jsonpath.JsonModel.model;
import static junit.framework.Assert.assertEquals;
/**
* Created by IntelliJ IDEA.
* User: kallestenflo
* Date: 3/11/12
* Time: 4:44 PM
*
*/
public class JsonModelSubModelDetachedTest {
public class Runner {
public final static String DOCUMENT =
"{ \"store\": {\n" +
@ -47,19 +40,16 @@ public class JsonModelSubModelDetachedTest {
" }\n" +
"}";
@Test
public void a_sub_model_can_be_detached() throws Exception {
JsonModel model = model(DOCUMENT);
JsonModel detachedModel = model.getSubModelDetached("$.store.book[*]");
public static void main(String[] args) {
detachedModel.opsForArray().add(1);
assertEquals(4, model.opsForArray("$.store.book").size());
assertEquals(5, detachedModel.opsForArray("$.store.book").size());
JsonPath jp = JsonPath.compile("$.store.book[3]");
ReadContext readContext = JsonPath.parse(DOCUMENT);
long start = System.currentTimeMillis();
for (long i = 0; i < 100000; i++) {
readContext.read(jp);
}
System.out.println(System.currentTimeMillis() - start);
}
}

2
json-path/src/test/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilterTest.java → json-path/src/test/java/com/jayway/jsonpath/internal/ArrayIndexFilterTest.java

@ -1,4 +1,4 @@
package com.jayway.jsonpath.internal.filter;
package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.JsonPath;
import org.hamcrest.Matchers;

88
json-path/src/test/java/com/jayway/jsonpath/internal/ArrayPathTokenTest.java

@ -0,0 +1,88 @@
package com.jayway.jsonpath.internal;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import static com.jayway.jsonpath.JsonPath.read;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.MapEntry.entry;
public class ArrayPathTokenTest extends TestBase {
@Test
public void array_can_select_single_index_by_context_length() {
Map<String, Object> result = read(ARRAY, "$[(@.length-1)]");
assertThat(result).contains(entry("foo", "foo-val-6"));
}
@Test
public void array_can_select_multiple_indexes() {
List<Map> result = read(ARRAY, "$[0,1]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-0"),
singletonMap("foo", "foo-val-1"));
}
@Test
public void array_can_be_sliced_to_2() {
List<Map> result = read(ARRAY, "$[:2]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-0"),
singletonMap("foo", "foo-val-1"));
}
@Test
public void array_can_be_sliced_to_2_from_tail() {
List<Map> result = read(ARRAY, "$[:-5]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-0"),
singletonMap("foo", "foo-val-1"));
}
@Test
public void array_can_be_sliced_from_2() {
List<Map> result = read(ARRAY, "$[5:]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-5"),
singletonMap("foo", "foo-val-6"));
}
@Test
public void array_can_be_sliced_from_2_from_tail() {
List<Map> result = read(ARRAY, "$[-2:]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-5"),
singletonMap("foo", "foo-val-6"));
}
@Test
public void array_can_be_sliced_between() {
List<Map> result = read(ARRAY, "$[2:4]");
assertThat(result).containsOnly(
singletonMap("foo", "foo-val-2"),
singletonMap("foo", "foo-val-3"));
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save