diff --git a/jsurfer-all/pom.xml b/jsurfer-all/pom.xml index 1c73c7e..c47a372 100644 --- a/jsurfer-all/pom.xml +++ b/jsurfer-all/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-all/src/test/java/org/jsfr/json/FastJsonParesrTest.java b/jsurfer-all/src/test/java/org/jsfr/json/FastJsonParesrTest.java index 8430e17..3146245 100644 --- a/jsurfer-all/src/test/java/org/jsfr/json/FastJsonParesrTest.java +++ b/jsurfer-all/src/test/java/org/jsfr/json/FastJsonParesrTest.java @@ -1,64 +1,17 @@ package org.jsfr.json; -import org.jsfr.json.compiler.JsonPathCompiler; import org.jsfr.json.provider.FastJsonProvider; import org.junit.Before; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; /** * Created by Leo on 2017/3/31. */ public class FastJsonParesrTest extends JsonSurferTest { - @Override @Before public void setUp() throws Exception { provider = FastJsonProvider.INSTANCE; surfer = new JsonSurfer(FastJsonParser.INSTANCE, provider); } - @Test - public void testSurfingIterator() throws Exception { - Iterator iterator = surfer.iterator(read("sample.json"), JsonPathCompiler.compile("$.store.book[*]")); - int count = 0; - while (iterator.hasNext()) { - LOGGER.info("Iterator next: {}", iterator.next()); - count++; - } - assertEquals(4, count); - } - - @Test - public void testResumableParser() throws Exception { - SurfingConfiguration config = surfer.configBuilder() - .bind("$.store.book[0]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("First pause"); - context.pause(); - } - }) - .bind("$.store.book[1]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("Second pause"); - context.pause(); - } - }).build(); - ResumableParser parser = surfer.createResumableParser(read("sample.json"), config); - assertFalse(parser.resume()); - LOGGER.info("Start parsing"); - parser.parse(); - LOGGER.info("Resume from the first pause"); - assertTrue(parser.resume()); - LOGGER.info("Resume from the second pause"); - assertTrue(parser.resume()); - LOGGER.info("Parsing stopped"); - assertFalse(parser.resume()); - } - } diff --git a/jsurfer-all/src/test/java/org/jsfr/json/GsonParserTest.java b/jsurfer-all/src/test/java/org/jsfr/json/GsonParserTest.java index 6ca60b0..0a75acd 100644 --- a/jsurfer-all/src/test/java/org/jsfr/json/GsonParserTest.java +++ b/jsurfer-all/src/test/java/org/jsfr/json/GsonParserTest.java @@ -24,106 +24,18 @@ package org.jsfr.json; -import com.google.gson.Gson; -import com.google.gson.stream.JsonReader; -import org.jsfr.json.compiler.JsonPathCompiler; import org.jsfr.json.provider.GsonProvider; import org.junit.Before; -import org.junit.Test; - -import java.io.Reader; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -import static org.junit.Assert.*; /** * Created by Leo on 2015/3/29. */ public class GsonParserTest extends JsonSurferTest { - @Override @Before public void setUp() throws Exception { provider = GsonProvider.INSTANCE; surfer = new JsonSurfer(GsonParser.INSTANCE, provider); } - @Test - public void testLargeJsonRawGson() throws Exception { - final AtomicLong counter = new AtomicLong(); - Gson gson = new Gson(); - JsonReader reader = new JsonReader(read("allthethings.json")); - long start = System.currentTimeMillis(); - reader.beginObject(); - reader.nextName(); - // $.builders - reader.beginObject(); - while (reader.hasNext()) { - reader.nextName(); - Map element = gson.fromJson(reader, Map.class); - Object value = ((Map) element.get("properties")).get("branch"); - counter.incrementAndGet(); - LOGGER.trace("JsonPath: {} value: {}", reader.getPath(), value); - } - LOGGER.info("Gson processes {} value in {} millisecond", counter.get(), System.currentTimeMillis() - start); - } - - @Test - public void testGsonTypeBindingOne() throws Exception { - Reader reader = read("sample.json"); - Book book = surfer.collectOne(reader, Book.class, JsonPathCompiler.compile("$..book[1]")); - assertEquals("Evelyn Waugh", book.getAuthor()); - } - - @Test - public void testGsonTypeBindingCollection() throws Exception { - Reader reader = read("sample.json"); - Collection book = surfer.collectAll(reader, Book.class, JsonPathCompiler.compile("$..book[0,1]")); - assertEquals(2, book.size()); - assertEquals("Nigel Rees", book.iterator().next().getAuthor()); - } - - @Test - public void testSurfingIterator() throws Exception { - Iterator iterator = surfer.iterator(read("sample.json"), JsonPathCompiler.compile("$.store.book[*]")); - int count = 0; - while (iterator.hasNext()) { - LOGGER.info("Iterator next: {}", iterator.next()); - count++; - } - assertEquals(4, count); - } - - @Test - public void testResumableParser() throws Exception { - SurfingConfiguration config = surfer.configBuilder() - .bind("$.store.book[0]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("First pause"); - context.pause(); - } - }) - .bind("$.store.book[1]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("Second pause"); - context.pause(); - } - }).build(); - ResumableParser parser = surfer.createResumableParser(read("sample.json"), config); - assertFalse(parser.resume()); - LOGGER.info("Start parsing"); - parser.parse(); - LOGGER.info("Resume from the first pause"); - assertTrue(parser.resume()); - LOGGER.info("Resume from the second pause"); - assertTrue(parser.resume()); - LOGGER.info("Parsing stopped"); - assertFalse(parser.resume()); - } - } diff --git a/jsurfer-all/src/test/java/org/jsfr/json/JacksonParserTest.java b/jsurfer-all/src/test/java/org/jsfr/json/JacksonParserTest.java index 774b269..70d4e26 100644 --- a/jsurfer-all/src/test/java/org/jsfr/json/JacksonParserTest.java +++ b/jsurfer-all/src/test/java/org/jsfr/json/JacksonParserTest.java @@ -24,22 +24,12 @@ package org.jsfr.json; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.jsfr.json.compiler.JsonPathCompiler; import org.jsfr.json.provider.JacksonProvider; import org.junit.Before; import org.junit.Test; -import java.io.Reader; -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.atomic.AtomicLong; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; @@ -48,89 +38,12 @@ */ public class JacksonParserTest extends JsonSurferTest { - @Override @Before public void setUp() throws Exception { provider = new JacksonProvider(); surfer = new JsonSurfer(JacksonParser.INSTANCE, provider); } - @Test - public void testLargeJsonJackson() throws Exception { - final AtomicLong counter = new AtomicLong(); - ObjectMapper om = new ObjectMapper(); - JsonFactory f = new JsonFactory(); - JsonParser jp = f.createParser(read("allthethings.json")); - long start = System.currentTimeMillis(); - jp.nextToken(); - jp.nextToken(); - jp.nextToken(); - while (jp.nextToken() == JsonToken.FIELD_NAME) { - if (jp.nextToken() == JsonToken.START_OBJECT) { - TreeNode tree = om.readTree(jp); - counter.incrementAndGet(); - LOGGER.trace("value: {}", tree); - } - } - jp.close(); - LOGGER.info("Jackson processes {} value in {} millisecond", counter.get(), System.currentTimeMillis() - start); - } - - @Test - public void testJacksonTypeBindingOne() throws Exception { - Reader reader = read("sample.json"); - Book book = surfer.collectOne(reader, Book.class, JsonPathCompiler.compile("$..book[1]")); - assertEquals("Evelyn Waugh", book.getAuthor()); - } - - @Test - public void testJacksonTypeBindingCollection() throws Exception { - Reader reader = read("sample.json"); - Collection book = surfer.collectAll(reader, Book.class, JsonPathCompiler.compile("$..book[0,1]")); - assertEquals(2, book.size()); - assertEquals("Nigel Rees", book.iterator().next().getAuthor()); - } - - @Test - public void testSurfingIterator() throws Exception { - Iterator iterator = surfer.iterator(read("sample.json"), JsonPathCompiler.compile("$.store.book[*]")); - int count = 0; - while (iterator.hasNext()) { - LOGGER.info("Iterator next: {}", iterator.next()); - count++; - } - assertEquals(4, count); - } - - @Test - public void testResumableParser() throws Exception { - SurfingConfiguration config = surfer.configBuilder() - .bind("$.store.book[0]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("First pause"); - context.pause(); - } - }) - .bind("$.store.book[1]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - LOGGER.info("Second pause"); - context.pause(); - } - }).build(); - ResumableParser parser = surfer.createResumableParser(read("sample.json"), config); - assertFalse(parser.resume()); - LOGGER.info("Start parsing"); - parser.parse(); - LOGGER.info("Resume from the first pause"); - assertTrue(parser.resume()); - LOGGER.info("Resume from the second pause"); - assertTrue(parser.resume()); - LOGGER.info("Parsing stopped"); - assertFalse(parser.resume()); - } - @Test public void testNonBlockingParser() throws Exception { JsonPathListener mockListener = mock(JsonPathListener.class); diff --git a/jsurfer-all/src/test/java/org/jsfr/json/JsonSimpleParserTest.java b/jsurfer-all/src/test/java/org/jsfr/json/JsonSimpleParserTest.java new file mode 100644 index 0000000..6d45056 --- /dev/null +++ b/jsurfer-all/src/test/java/org/jsfr/json/JsonSimpleParserTest.java @@ -0,0 +1,42 @@ +package org.jsfr.json; + +import org.jsfr.json.provider.JsonSimpleProvider; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Created by Leo on 2017/8/26. + */ +public class JsonSimpleParserTest extends JsonSurferTest { + + @Before + public void setUp() throws Exception { + provider = JsonSimpleProvider.INSTANCE; + surfer = new JsonSurfer(JsonSimpleParser.INSTANCE, provider); + } + + @Override + public void testTypeBindingOne() throws Exception { + // ignore + } + + @Ignore + @Override + public void testTypeBindingCollection() throws Exception { + // ignore + } + + @Test(expected = UnsupportedOperationException.class) + @Override + public void testSurfingIterator() throws Exception { + super.testSurfingIterator(); + } + + @Test(expected = UnsupportedOperationException.class) + @Override + public void testResumableParser() throws Exception { + super.testResumableParser(); + } + +} diff --git a/jsurfer-all/src/test/java/org/jsfr/json/JsonSurferTest.java b/jsurfer-all/src/test/java/org/jsfr/json/JsonSurferTest.java index 4836edb..930535c 100644 --- a/jsurfer-all/src/test/java/org/jsfr/json/JsonSurferTest.java +++ b/jsurfer-all/src/test/java/org/jsfr/json/JsonSurferTest.java @@ -25,13 +25,12 @@ package org.jsfr.json; import com.google.common.io.Resources; +import org.hamcrest.CustomMatcher; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.jsfr.json.compiler.JsonPathCompiler; import org.jsfr.json.provider.JavaCollectionProvider; import org.jsfr.json.provider.JsonProvider; -import org.jsfr.json.provider.JsonSimpleProvider; -import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,8 +43,7 @@ import java.util.HashMap; import java.util.Iterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.argThat; @@ -53,7 +51,7 @@ import static org.mockito.Mockito.*; import static org.mockito.Mockito.isA; -public class JsonSurferTest { +public abstract class JsonSurferTest { protected final static Logger LOGGER = LoggerFactory.getLogger(JsonSurferTest.class); @@ -66,10 +64,59 @@ public void onValue(Object value, ParsingContext context) { } }; - @Before - public void setUp() throws Exception { - provider = JsonSimpleProvider.INSTANCE; - surfer = new JsonSurfer(JsonSimpleParser.INSTANCE, provider); + @Test + public void testTypeBindingOne() throws Exception { + Reader reader = read("sample.json"); + Book book = surfer.collectOne(reader, Book.class, JsonPathCompiler.compile("$..book[1]")); + assertEquals("Evelyn Waugh", book.getAuthor()); + } + + @Test + public void testTypeBindingCollection() throws Exception { + Reader reader = read("sample.json"); + Collection book = surfer.collectAll(reader, Book.class, JsonPathCompiler.compile("$..book[0,1]")); + assertEquals(2, book.size()); + assertEquals("Nigel Rees", book.iterator().next().getAuthor()); + } + + @Test + public void testSurfingIterator() throws Exception { + Iterator iterator = surfer.iterator(read("sample.json"), JsonPathCompiler.compile("$.store.book[*]")); + int count = 0; + while (iterator.hasNext()) { + LOGGER.info("Iterator next: {}", iterator.next()); + count++; + } + assertEquals(4, count); + } + + @Test + public void testResumableParser() throws Exception { + SurfingConfiguration config = surfer.configBuilder() + .bind("$.store.book[0]", new JsonPathListener() { + @Override + public void onValue(Object value, ParsingContext context) { + LOGGER.info("First pause"); + context.pause(); + } + }) + .bind("$.store.book[1]", new JsonPathListener() { + @Override + public void onValue(Object value, ParsingContext context) { + LOGGER.info("Second pause"); + context.pause(); + } + }).build(); + ResumableParser parser = surfer.createResumableParser(read("sample.json"), config); + assertFalse(parser.resume()); + LOGGER.info("Start parsing"); + parser.parse(); + LOGGER.info("Resume from the first pause"); + assertTrue(parser.resume()); + LOGGER.info("Resume from the second pause"); + assertTrue(parser.resume()); + LOGGER.info("Parsing stopped"); + assertFalse(parser.resume()); } @Test @@ -84,51 +131,49 @@ public void onValue(Object value, ParsingContext context) { public void onValue(Object value, ParsingContext context) { assertEquals("bar", context.load("foo", String.class)); } - }) - .bind("$.store.book[0]", new JsonPathListener() { - @Override - public void onValue(Object value, ParsingContext context) { - assertNull(context.load("foo", String.class)); - } - }).buildAndSurf(read("sample.json")); + }).bind("$.store.book[0]", new JsonPathListener() { + @Override + public void onValue(Object value, ParsingContext context) { + assertNull(context.load("foo", String.class)); + } + }).buildAndSurf(read("sample.json")); } @Test public void testJsonPathFilterEqualNumber() throws Exception { JsonPathListener mockListener = mock(JsonPathListener.class); surfer.configBuilder().bind("$.store.book[?(@.price==8.95)]", mockListener) - .buildAndSurf(read("sample.json")); + .buildAndSurf(read("sample_filter.json")); + + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Sayings of the Century").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book = provider.createObject(); - provider.put(book, "category", provider.primitive("reference")); - provider.put(book, "author", provider.primitive("Nigel Rees")); - provider.put(book, "title", provider.primitive("Sayings of the Century")); - provider.put(book, "price", provider.primitive(8.95)); - verify(mockListener).onValue(eq(book), any(ParsingContext.class)); - verify(mockListener, times(1)).onValue(any(), any(ParsingContext.class)); } @Test public void testJsonPathFilterGreaterThan() throws Exception { JsonPathListener mockListener = mock(JsonPathListener.class); surfer.configBuilder().bind("$.store.book[?(@.price>10)]", mockListener) - .buildAndSurf(read("sample.json")); + .buildAndSurf(read("sample_filter.json")); - Object book1 = provider.createObject(); - provider.put(book1, "category", provider.primitive("fiction")); - provider.put(book1, "author", provider.primitive("Evelyn Waugh")); - provider.put(book1, "title", provider.primitive("Sword of Honour")); - provider.put(book1, "price", provider.primitive(12.99)); - verify(mockListener).onValue(eq(book1), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Sword of Honour").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); + + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("The Lord of the Rings").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book2 = provider.createObject(); - provider.put(book2, "category", provider.primitive("fiction")); - provider.put(book2, "author", provider.primitive("J. R. R. Tolkien")); - provider.put(book2, "title", provider.primitive("The Lord of the Rings")); - provider.put(book2, "isbn", provider.primitive("0-395-19395-8")); - provider.put(book2, "price", provider.primitive(22.99)); - verify(mockListener).onValue(eq(book2), any(ParsingContext.class)); - verify(mockListener, times(2)).onValue(any(), any(ParsingContext.class)); } @Test @@ -154,90 +199,98 @@ public void testJsonPathFilterLessThan() throws Exception { verify(mockListener, times(2)).onValue(any(), any(ParsingContext.class)); } + @Test + public void testJsonPathFilterEqualString1() throws Exception { + JsonPathListener mockListener = mock(JsonPathListener.class); + surfer.configBuilder().bind("$.store.book[?(@.description.year=='2010')]", mockListener) + .buildAndSurf(read("sample_filter.json")); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("Test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Sword of Honour").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); + } + @Test public void testJsonPathFilterEqualString() throws Exception { + JsonPathListener mockListener = mock(JsonPathListener.class); surfer.configBuilder().bind("$.store.book[?(@.category=='fiction')]", mockListener) - .buildAndSurf(read("sample.json")); + .buildAndSurf(read("sample_filter.json")); - Object book1 = provider.createObject(); - provider.put(book1, "category", provider.primitive("fiction")); - provider.put(book1, "author", provider.primitive("Evelyn Waugh")); - provider.put(book1, "title", provider.primitive("Sword of Honour")); - provider.put(book1, "price", provider.primitive(12.99)); - verify(mockListener).onValue(eq(book1), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Sword of Honour").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book2 = provider.createObject(); - provider.put(book2, "category", provider.primitive("fiction")); - provider.put(book2, "author", provider.primitive("J. R. R. Tolkien")); - provider.put(book2, "title", provider.primitive("The Lord of the Rings")); - provider.put(book2, "isbn", provider.primitive("0-395-19395-8")); - provider.put(book2, "price", provider.primitive(22.99)); - verify(mockListener).onValue(eq(book2), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("The Lord of the Rings").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); + + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Moby Dick").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book3 = provider.createObject(); - provider.put(book3, "category", provider.primitive("fiction")); - provider.put(book3, "author", provider.primitive("Herman Melville")); - provider.put(book3, "title", provider.primitive("Moby Dick")); - provider.put(book3, "isbn", provider.primitive("0-553-21311-3")); - provider.put(book3, "price", provider.primitive(8.99)); - verify(mockListener).onValue(eq(book3), any(ParsingContext.class)); - verify(mockListener, times(3)).onValue(any(), any(ParsingContext.class)); } @Test public void testJsonPathFilterExistence() throws Exception { JsonPathListener mockListener = mock(JsonPathListener.class); surfer.configBuilder().bind("$.store.book[?(@.isbn)]", mockListener) - .buildAndSurf(read("sample.json")); + .buildAndSurf(read("sample_filter.json")); - Object book2 = provider.createObject(); - provider.put(book2, "category", provider.primitive("fiction")); - provider.put(book2, "author", provider.primitive("J. R. R. Tolkien")); - provider.put(book2, "title", provider.primitive("The Lord of the Rings")); - provider.put(book2, "isbn", provider.primitive("0-395-19395-8")); - provider.put(book2, "price", provider.primitive(22.99)); - verify(mockListener).onValue(eq(book2), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("The Lord of the Rings").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); + + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Moby Dick").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book3 = provider.createObject(); - provider.put(book3, "category", provider.primitive("fiction")); - provider.put(book3, "author", provider.primitive("Herman Melville")); - provider.put(book3, "title", provider.primitive("Moby Dick")); - provider.put(book3, "isbn", provider.primitive("0-553-21311-3")); - provider.put(book3, "price", provider.primitive(8.99)); - verify(mockListener).onValue(eq(book3), any(ParsingContext.class)); - verify(mockListener, times(2)).onValue(any(), any(ParsingContext.class)); } @Test public void testJsonPathFilterAggregate() throws Exception { JsonPathListener mockListener = mock(JsonPathListener.class); surfer.configBuilder().bind("$.store.book[?(@.price < 10 || @.category && @.isbn && @.price>10)]", mockListener) - .buildAndSurf(read("sample.json")); + .buildAndSurf(read("sample_filter.json")); - Object book1 = provider.createObject(); - provider.put(book1, "category", provider.primitive("reference")); - provider.put(book1, "author", provider.primitive("Nigel Rees")); - provider.put(book1, "title", provider.primitive("Sayings of the Century")); - provider.put(book1, "price", provider.primitive(8.95)); - verify(mockListener).onValue(eq(book1), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Sayings of the Century").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book2 = provider.createObject(); - provider.put(book2, "category", provider.primitive("fiction")); - provider.put(book2, "author", provider.primitive("J. R. R. Tolkien")); - provider.put(book2, "title", provider.primitive("The Lord of the Rings")); - provider.put(book2, "isbn", provider.primitive("0-395-19395-8")); - provider.put(book2, "price", provider.primitive(22.99)); - verify(mockListener).onValue(eq(book2), any(ParsingContext.class)); + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("The Lord of the Rings").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); + + verify(mockListener, times(1)).onValue(argThat(new CustomMatcher("test filter") { + @Override + public boolean matches(Object o) { + return provider.primitive("Moby Dick").equals(provider.resolve(o, "title")); + } + }), any(ParsingContext.class)); - Object book3 = provider.createObject(); - provider.put(book3, "category", provider.primitive("fiction")); - provider.put(book3, "author", provider.primitive("Herman Melville")); - provider.put(book3, "title", provider.primitive("Moby Dick")); - provider.put(book3, "isbn", provider.primitive("0-553-21311-3")); - provider.put(book3, "price", provider.primitive(8.99)); - verify(mockListener).onValue(eq(book3), any(ParsingContext.class)); - verify(mockListener, times(3)).onValue(any(), any(ParsingContext.class)); } @Test diff --git a/jsurfer-all/src/test/resources/sample_filter.json b/jsurfer-all/src/test/resources/sample_filter.json new file mode 100644 index 0000000..90cdbfe --- /dev/null +++ b/jsurfer-all/src/test/resources/sample_filter.json @@ -0,0 +1,44 @@ +{ + "store": { + "book": [ + { + "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { + "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99, + "description": { + "year": "2010" + } + }, + { + "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + }, + { + "category": "fiction", + "author": "J. R. R. Tolkien", + "title": "The Lord of the Rings", + "isbn": "0-395-19395-8", + "price": 22.99 + } + ], + "car": [ + "ferrari", + "lamborghini" + ], + "bicycle": { + "color": "red", + "price": 19.95 + } + }, + "expensive": 10 +} \ No newline at end of file diff --git a/jsurfer-benchmark/pom.xml b/jsurfer-benchmark/pom.xml index 0c19b46..aa6d405 100644 --- a/jsurfer-benchmark/pom.xml +++ b/jsurfer-benchmark/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-core/pom.xml b/jsurfer-core/pom.xml index e76ad28..10b12ed 100644 --- a/jsurfer-core/pom.xml +++ b/jsurfer-core/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPath.tokens b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPath.tokens index a91e170..88d248a 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPath.tokens +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPath.tokens @@ -31,7 +31,7 @@ WS=22 '.'=9 '[?('=10 ')]'=11 -'@.'=12 +'@'=12 '>'=13 '<'=14 '=='=15 diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathBaseVisitor.java b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathBaseVisitor.java index 2a4c4e7..1a8b643 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathBaseVisitor.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathBaseVisitor.java @@ -20,6 +20,13 @@ public class JsonPathBaseVisitor extends AbstractParseTreeVisitor implemen * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitPath(JsonPathParser.PathContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelativePath(JsonPathParser.RelativePathContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * @@ -103,40 +110,40 @@ public class JsonPathBaseVisitor extends AbstractParseTreeVisitor implemen *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExpr(JsonPathParser.ExprContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterExpr(JsonPathParser.FilterExprContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExprExist(JsonPathParser.ExprExistContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterExist(JsonPathParser.FilterExistContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExprGtNum(JsonPathParser.ExprGtNumContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterGtNum(JsonPathParser.FilterGtNumContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExprLtNum(JsonPathParser.ExprLtNumContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterLtNum(JsonPathParser.FilterLtNumContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExprEqualNum(JsonPathParser.ExprEqualNumContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterEqualNum(JsonPathParser.FilterEqualNumContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitExprEqualStr(JsonPathParser.ExprEqualStrContext ctx) { return visitChildren(ctx); } + @Override public T visitFilterEqualStr(JsonPathParser.FilterEqualStrContext ctx) { return visitChildren(ctx); } } \ No newline at end of file diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathCompiler.java b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathCompiler.java index 5400472..cc2b827 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathCompiler.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathCompiler.java @@ -39,35 +39,37 @@ */ public class JsonPathCompiler extends JsonPathBaseVisitor { - private JsonPath.Builder builder; + private JsonPath.Builder pathBuilder; private FilterBuilder filterBuilder; - public JsonPath.Builder getBuilder() { - return builder; - } + private JsonPath.Builder filterPathBuilder; @Override public Void visitPath(JsonPathParser.PathContext ctx) { - builder = JsonPath.Builder.start(); + pathBuilder = JsonPath.Builder.start(); return super.visitPath(ctx); } + private JsonPath.Builder currentPathBuilder() { + return filterPathBuilder != null ? filterPathBuilder : pathBuilder; + } + @Override public Void visitSearchChild(JsonPathParser.SearchChildContext ctx) { - builder.scan().child(ctx.KEY().getText()); + currentPathBuilder().scan().child(ctx.KEY().getText()); return super.visitSearchChild(ctx); } @Override public Void visitSearch(JsonPathParser.SearchContext ctx) { - builder.scan(); + currentPathBuilder().scan(); return super.visitSearch(ctx); } @Override public Void visitChildNode(JsonPathParser.ChildNodeContext ctx) { - builder.child(ctx.KEY().getText()); + currentPathBuilder().child(ctx.KEY().getText()); return super.visitChildNode(ctx); } @@ -79,7 +81,7 @@ public Void visitChildrenNode(JsonPathParser.ChildrenNodeContext ctx) { String quotedString = node.getText(); strings[i++] = removeQuote(quotedString); } - builder.children(strings); + currentPathBuilder().children(strings); return super.visitChildren(ctx); } @@ -89,7 +91,7 @@ private String removeQuote(String quotedString) { @Override public Void visitIndex(JsonPathParser.IndexContext ctx) { - builder.index(Integer.parseInt(ctx.NUM().getText())); + currentPathBuilder().index(Integer.parseInt(ctx.NUM().getText())); return super.visitIndex(ctx); } @@ -100,7 +102,7 @@ public Void visitIndexes(JsonPathParser.IndexesContext ctx) { for (TerminalNode key : ctx.NUM()) { keys[i++] = Integer.parseInt(key.getText()); } - builder.indexes(keys); + currentPathBuilder().indexes(keys); return super.visitIndexes(ctx); } @@ -121,87 +123,98 @@ public Void visitSlicing(JsonPathParser.SlicingContext ctx) { } } right = temp; - builder.slicing(left, right); + pathBuilder.slicing(left, right); return super.visitSlicing(ctx); } @Override public Void visitAnyChild(JsonPathParser.AnyChildContext ctx) { - builder.anyChild(); + currentPathBuilder().anyChild(); return super.visitAnyChild(ctx); } @Override public Void visitAnyIndex(JsonPathParser.AnyIndexContext ctx) { - builder.anyIndex(); + currentPathBuilder().anyIndex(); return super.visitAnyIndex(ctx); } @Override public Void visitAny(JsonPathParser.AnyContext ctx) { - builder.any(); + currentPathBuilder().any(); return super.visitAny(ctx); } @Override public Void visitFilter(JsonPathParser.FilterContext ctx) { - builder.any(); + pathBuilder.any(); filterBuilder = new FilterBuilder(); Void rst = super.visitFilter(ctx); - builder.withFilter(filterBuilder.build()); + pathBuilder.withFilter(filterBuilder.build()); return rst; } @Override - public Void visitExpr(JsonPathParser.ExprContext ctx) { + public Void visitFilterExpr(JsonPathParser.FilterExprContext ctx) { Void rst; if (ctx.AndOperator() != null) { filterBuilder.startAndPredicate(); - rst = super.visitExpr(ctx); + rst = super.visitFilterExpr(ctx); filterBuilder.endAndPredicate(); } else if (ctx.OrOperator() != null) { filterBuilder.startOrPredicate(); - rst = super.visitExpr(ctx); + rst = super.visitFilterExpr(ctx); filterBuilder.endOrPredicate(); } else { - rst = super.visitExpr(ctx); + rst = super.visitFilterExpr(ctx); } return rst; } @Override - public Void visitExprEqualNum(JsonPathParser.ExprEqualNumContext ctx) { - JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); - filterBuilder.append(new EqualityNumPredicate(relativePath, new BigDecimal(ctx.NUM().getText()))); - return super.visitExprEqualNum(ctx); + public Void visitFilterEqualNum(JsonPathParser.FilterEqualNumContext ctx) { +// JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); + filterPathBuilder = JsonPath.Builder.start(); + Void rst = super.visitFilterEqualNum(ctx); + filterBuilder.append(new EqualityNumPredicate(filterPathBuilder.build(), new BigDecimal(ctx.NUM().getText()))); + filterPathBuilder = null; + return rst; } @Override - public Void visitExprExist(JsonPathParser.ExprExistContext ctx) { - JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); - filterBuilder.append(new ExistencePredicate(relativePath)); - return super.visitExprExist(ctx); + public Void visitFilterExist(JsonPathParser.FilterExistContext ctx) { + filterPathBuilder = JsonPath.Builder.start(); + Void rst = super.visitFilterExist(ctx); + filterBuilder.append(new ExistencePredicate(filterPathBuilder.build())); + filterPathBuilder = null; + return rst; } @Override - public Void visitExprGtNum(JsonPathParser.ExprGtNumContext ctx) { - JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); - filterBuilder.append(new GreaterThanNumPredicate(relativePath, new BigDecimal(ctx.NUM().getText()))); - return super.visitExprGtNum(ctx); + public Void visitFilterGtNum(JsonPathParser.FilterGtNumContext ctx) { + filterPathBuilder = JsonPath.Builder.start(); + Void rst = super.visitFilterGtNum(ctx); + filterBuilder.append(new GreaterThanNumPredicate(filterPathBuilder.build(), new BigDecimal(ctx.NUM().getText()))); + filterPathBuilder = null; + return rst; } @Override - public Void visitExprLtNum(JsonPathParser.ExprLtNumContext ctx) { - JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); - filterBuilder.append(new LessThanNumPredicate(relativePath, new BigDecimal(ctx.NUM().getText()))); - return super.visitExprLtNum(ctx); + public Void visitFilterLtNum(JsonPathParser.FilterLtNumContext ctx) { + filterPathBuilder = JsonPath.Builder.start(); + Void rst = super.visitFilterLtNum(ctx); + filterBuilder.append(new LessThanNumPredicate(filterPathBuilder.build(), new BigDecimal(ctx.NUM().getText()))); + filterPathBuilder = null; + return rst; } @Override - public Void visitExprEqualStr(JsonPathParser.ExprEqualStrContext ctx) { - JsonPath relativePath = JsonPath.Builder.start().child(ctx.KEY().getText()).build(); - filterBuilder.append(new EqualityStrPredicate(relativePath, removeQuote(ctx.QUOTED_STRING().getText()))); - return super.visitExprEqualStr(ctx); + public Void visitFilterEqualStr(JsonPathParser.FilterEqualStrContext ctx) { + filterPathBuilder = JsonPath.Builder.start(); + Void rst = super.visitFilterEqualStr(ctx); + filterBuilder.append(new EqualityStrPredicate(filterPathBuilder.build(), removeQuote(ctx.QUOTED_STRING().getText()))); + filterPathBuilder = null; + return rst; } public static JsonPath[] compile(String... paths) { @@ -220,7 +233,7 @@ public static JsonPath compile(String path) { JsonPathParser.PathContext tree = parser.path(); JsonPathCompiler compiler = new JsonPathCompiler(); compiler.visit(tree); - return compiler.getBuilder().build(); + return compiler.pathBuilder.build(); } // public static void main(String[] s) { diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.java b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.java index 7ff1ee6..3e6e2a5 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.java @@ -39,7 +39,7 @@ public class JsonPathLexer extends Lexer { private static final String[] _LITERAL_NAMES = { null, "'$'", "'..'", "'.*'", "'[*]'", "'*'", "'['", "']'", "','", "'.'", - "'[?('", "')]'", "'@.'", "'>'", "'<'", "'=='", "':'", "'&&'", "'||'" + "'[?('", "')]'", "'@'", "'>'", "'<'", "'=='", "':'", "'&&'", "'||'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -104,64 +104,63 @@ public JsonPathLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\30\u00b6\b\1\4\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\30\u00b5\b\1\4\2"+ "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\4\3"+ "\5\3\5\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\13"+ - "\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21"+ - "\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\24\5\24j\n\24\3\24\3\24\3\24\6\24"+ - "o\n\24\r\24\16\24p\3\24\5\24t\n\24\3\24\5\24w\n\24\3\24\3\24\3\24\3\24"+ - "\5\24}\n\24\3\24\5\24\u0080\n\24\3\25\3\25\3\25\7\25\u0085\n\25\f\25\16"+ - "\25\u0088\13\25\5\25\u008a\n\25\3\26\3\26\5\26\u008e\n\26\3\26\3\26\3"+ - "\27\3\27\3\27\3\27\7\27\u0096\n\27\f\27\16\27\u0099\13\27\3\27\3\27\3"+ - "\30\3\30\6\30\u009f\n\30\r\30\16\30\u00a0\3\31\3\31\3\31\5\31\u00a6\n"+ - "\31\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\34\6\34\u00b1\n\34\r\34"+ - "\16\34\u00b2\3\34\3\34\2\2\35\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13"+ - "\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\2+\2-\26/\27\61\2"+ - "\63\2\65\2\67\30\3\2\13\3\2\62;\3\2\63;\4\2GGgg\4\2--//\4\2))^^\r\2\13"+ - "\f\17\17\"\"$$(,..\60\60<<>B]_~~\n\2$$\61\61^^ddhhppttvv\5\2\62;CHch\5"+ - "\2\13\f\17\17\"\"\2\u00c0\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2"+ - "\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2"+ - "\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3"+ - "\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2-\3\2\2\2\2/\3\2"+ - "\2\2\2\67\3\2\2\2\39\3\2\2\2\5;\3\2\2\2\7>\3\2\2\2\tA\3\2\2\2\13E\3\2"+ - "\2\2\rG\3\2\2\2\17I\3\2\2\2\21K\3\2\2\2\23M\3\2\2\2\25O\3\2\2\2\27S\3"+ - "\2\2\2\31V\3\2\2\2\33Y\3\2\2\2\35[\3\2\2\2\37]\3\2\2\2!`\3\2\2\2#b\3\2"+ - "\2\2%e\3\2\2\2\'\177\3\2\2\2)\u0089\3\2\2\2+\u008b\3\2\2\2-\u0091\3\2"+ - "\2\2/\u009e\3\2\2\2\61\u00a2\3\2\2\2\63\u00a7\3\2\2\2\65\u00ad\3\2\2\2"+ - "\67\u00b0\3\2\2\29:\7&\2\2:\4\3\2\2\2;<\7\60\2\2<=\7\60\2\2=\6\3\2\2\2"+ - ">?\7\60\2\2?@\7,\2\2@\b\3\2\2\2AB\7]\2\2BC\7,\2\2CD\7_\2\2D\n\3\2\2\2"+ - "EF\7,\2\2F\f\3\2\2\2GH\7]\2\2H\16\3\2\2\2IJ\7_\2\2J\20\3\2\2\2KL\7.\2"+ - "\2L\22\3\2\2\2MN\7\60\2\2N\24\3\2\2\2OP\7]\2\2PQ\7A\2\2QR\7*\2\2R\26\3"+ - "\2\2\2ST\7+\2\2TU\7_\2\2U\30\3\2\2\2VW\7B\2\2WX\7\60\2\2X\32\3\2\2\2Y"+ - "Z\7@\2\2Z\34\3\2\2\2[\\\7>\2\2\\\36\3\2\2\2]^\7?\2\2^_\7?\2\2_ \3\2\2"+ - "\2`a\7<\2\2a\"\3\2\2\2bc\7(\2\2cd\7(\2\2d$\3\2\2\2ef\7~\2\2fg\7~\2\2g"+ - "&\3\2\2\2hj\7/\2\2ih\3\2\2\2ij\3\2\2\2jk\3\2\2\2kl\5)\25\2ln\7\60\2\2"+ - "mo\t\2\2\2nm\3\2\2\2op\3\2\2\2pn\3\2\2\2pq\3\2\2\2qs\3\2\2\2rt\5+\26\2"+ - "sr\3\2\2\2st\3\2\2\2t\u0080\3\2\2\2uw\7/\2\2vu\3\2\2\2vw\3\2\2\2wx\3\2"+ - "\2\2xy\5)\25\2yz\5+\26\2z\u0080\3\2\2\2{}\7/\2\2|{\3\2\2\2|}\3\2\2\2}"+ - "~\3\2\2\2~\u0080\5)\25\2\177i\3\2\2\2\177v\3\2\2\2\177|\3\2\2\2\u0080"+ - "(\3\2\2\2\u0081\u008a\7\62\2\2\u0082\u0086\t\3\2\2\u0083\u0085\t\2\2\2"+ - "\u0084\u0083\3\2\2\2\u0085\u0088\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0087"+ - "\3\2\2\2\u0087\u008a\3\2\2\2\u0088\u0086\3\2\2\2\u0089\u0081\3\2\2\2\u0089"+ - "\u0082\3\2\2\2\u008a*\3\2\2\2\u008b\u008d\t\4\2\2\u008c\u008e\t\5\2\2"+ - "\u008d\u008c\3\2\2\2\u008d\u008e\3\2\2\2\u008e\u008f\3\2\2\2\u008f\u0090"+ - "\5)\25\2\u0090,\3\2\2\2\u0091\u0097\7)\2\2\u0092\u0096\n\6\2\2\u0093\u0094"+ - "\7^\2\2\u0094\u0096\13\2\2\2\u0095\u0092\3\2\2\2\u0095\u0093\3\2\2\2\u0096"+ - "\u0099\3\2\2\2\u0097\u0095\3\2\2\2\u0097\u0098\3\2\2\2\u0098\u009a\3\2"+ - "\2\2\u0099\u0097\3\2\2\2\u009a\u009b\7)\2\2\u009b.\3\2\2\2\u009c\u009f"+ - "\5\61\31\2\u009d\u009f\n\7\2\2\u009e\u009c\3\2\2\2\u009e\u009d\3\2\2\2"+ - "\u009f\u00a0\3\2\2\2\u00a0\u009e\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\60"+ - "\3\2\2\2\u00a2\u00a5\7^\2\2\u00a3\u00a6\t\b\2\2\u00a4\u00a6\5\63\32\2"+ - "\u00a5\u00a3\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6\62\3\2\2\2\u00a7\u00a8"+ - "\7w\2\2\u00a8\u00a9\5\65\33\2\u00a9\u00aa\5\65\33\2\u00aa\u00ab\5\65\33"+ - "\2\u00ab\u00ac\5\65\33\2\u00ac\64\3\2\2\2\u00ad\u00ae\t\t\2\2\u00ae\66"+ - "\3\2\2\2\u00af\u00b1\t\n\2\2\u00b0\u00af\3\2\2\2\u00b1\u00b2\3\2\2\2\u00b2"+ - "\u00b0\3\2\2\2\u00b2\u00b3\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b4\u00b5\b\34"+ - "\2\2\u00b58\3\2\2\2\22\2ipsv|\177\u0086\u0089\u008d\u0095\u0097\u009e"+ - "\u00a0\u00a5\u00b2\3\b\2\2"; + "\3\13\3\f\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21\3\21"+ + "\3\22\3\22\3\22\3\23\3\23\3\23\3\24\5\24i\n\24\3\24\3\24\3\24\6\24n\n"+ + "\24\r\24\16\24o\3\24\5\24s\n\24\3\24\5\24v\n\24\3\24\3\24\3\24\3\24\5"+ + "\24|\n\24\3\24\5\24\177\n\24\3\25\3\25\3\25\7\25\u0084\n\25\f\25\16\25"+ + "\u0087\13\25\5\25\u0089\n\25\3\26\3\26\5\26\u008d\n\26\3\26\3\26\3\27"+ + "\3\27\3\27\3\27\7\27\u0095\n\27\f\27\16\27\u0098\13\27\3\27\3\27\3\30"+ + "\3\30\6\30\u009e\n\30\r\30\16\30\u009f\3\31\3\31\3\31\5\31\u00a5\n\31"+ + "\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\34\6\34\u00b0\n\34\r\34\16"+ + "\34\u00b1\3\34\3\34\2\2\35\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25"+ + "\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\2+\2-\26/\27\61\2\63"+ + "\2\65\2\67\30\3\2\13\3\2\62;\3\2\63;\4\2GGgg\4\2--//\4\2))^^\r\2\13\f"+ + "\17\17\"\"$$(,..\60\60<<>B]_~~\n\2$$\61\61^^ddhhppttvv\5\2\62;CHch\5\2"+ + "\13\f\17\17\"\"\2\u00bf\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2"+ + "\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25"+ + "\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2"+ + "\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+ + "\2\2\67\3\2\2\2\39\3\2\2\2\5;\3\2\2\2\7>\3\2\2\2\tA\3\2\2\2\13E\3\2\2"+ + "\2\rG\3\2\2\2\17I\3\2\2\2\21K\3\2\2\2\23M\3\2\2\2\25O\3\2\2\2\27S\3\2"+ + "\2\2\31V\3\2\2\2\33X\3\2\2\2\35Z\3\2\2\2\37\\\3\2\2\2!_\3\2\2\2#a\3\2"+ + "\2\2%d\3\2\2\2\'~\3\2\2\2)\u0088\3\2\2\2+\u008a\3\2\2\2-\u0090\3\2\2\2"+ + "/\u009d\3\2\2\2\61\u00a1\3\2\2\2\63\u00a6\3\2\2\2\65\u00ac\3\2\2\2\67"+ + "\u00af\3\2\2\29:\7&\2\2:\4\3\2\2\2;<\7\60\2\2<=\7\60\2\2=\6\3\2\2\2>?"+ + "\7\60\2\2?@\7,\2\2@\b\3\2\2\2AB\7]\2\2BC\7,\2\2CD\7_\2\2D\n\3\2\2\2EF"+ + "\7,\2\2F\f\3\2\2\2GH\7]\2\2H\16\3\2\2\2IJ\7_\2\2J\20\3\2\2\2KL\7.\2\2"+ + "L\22\3\2\2\2MN\7\60\2\2N\24\3\2\2\2OP\7]\2\2PQ\7A\2\2QR\7*\2\2R\26\3\2"+ + "\2\2ST\7+\2\2TU\7_\2\2U\30\3\2\2\2VW\7B\2\2W\32\3\2\2\2XY\7@\2\2Y\34\3"+ + "\2\2\2Z[\7>\2\2[\36\3\2\2\2\\]\7?\2\2]^\7?\2\2^ \3\2\2\2_`\7<\2\2`\"\3"+ + "\2\2\2ab\7(\2\2bc\7(\2\2c$\3\2\2\2de\7~\2\2ef\7~\2\2f&\3\2\2\2gi\7/\2"+ + "\2hg\3\2\2\2hi\3\2\2\2ij\3\2\2\2jk\5)\25\2km\7\60\2\2ln\t\2\2\2ml\3\2"+ + "\2\2no\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2\2qs\5+\26\2rq\3\2\2\2rs\3\2"+ + "\2\2s\177\3\2\2\2tv\7/\2\2ut\3\2\2\2uv\3\2\2\2vw\3\2\2\2wx\5)\25\2xy\5"+ + "+\26\2y\177\3\2\2\2z|\7/\2\2{z\3\2\2\2{|\3\2\2\2|}\3\2\2\2}\177\5)\25"+ + "\2~h\3\2\2\2~u\3\2\2\2~{\3\2\2\2\177(\3\2\2\2\u0080\u0089\7\62\2\2\u0081"+ + "\u0085\t\3\2\2\u0082\u0084\t\2\2\2\u0083\u0082\3\2\2\2\u0084\u0087\3\2"+ + "\2\2\u0085\u0083\3\2\2\2\u0085\u0086\3\2\2\2\u0086\u0089\3\2\2\2\u0087"+ + "\u0085\3\2\2\2\u0088\u0080\3\2\2\2\u0088\u0081\3\2\2\2\u0089*\3\2\2\2"+ + "\u008a\u008c\t\4\2\2\u008b\u008d\t\5\2\2\u008c\u008b\3\2\2\2\u008c\u008d"+ + "\3\2\2\2\u008d\u008e\3\2\2\2\u008e\u008f\5)\25\2\u008f,\3\2\2\2\u0090"+ + "\u0096\7)\2\2\u0091\u0095\n\6\2\2\u0092\u0093\7^\2\2\u0093\u0095\13\2"+ + "\2\2\u0094\u0091\3\2\2\2\u0094\u0092\3\2\2\2\u0095\u0098\3\2\2\2\u0096"+ + "\u0094\3\2\2\2\u0096\u0097\3\2\2\2\u0097\u0099\3\2\2\2\u0098\u0096\3\2"+ + "\2\2\u0099\u009a\7)\2\2\u009a.\3\2\2\2\u009b\u009e\5\61\31\2\u009c\u009e"+ + "\n\7\2\2\u009d\u009b\3\2\2\2\u009d\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f"+ + "\u009d\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\60\3\2\2\2\u00a1\u00a4\7^\2\2"+ + "\u00a2\u00a5\t\b\2\2\u00a3\u00a5\5\63\32\2\u00a4\u00a2\3\2\2\2\u00a4\u00a3"+ + "\3\2\2\2\u00a5\62\3\2\2\2\u00a6\u00a7\7w\2\2\u00a7\u00a8\5\65\33\2\u00a8"+ + "\u00a9\5\65\33\2\u00a9\u00aa\5\65\33\2\u00aa\u00ab\5\65\33\2\u00ab\64"+ + "\3\2\2\2\u00ac\u00ad\t\t\2\2\u00ad\66\3\2\2\2\u00ae\u00b0\t\n\2\2\u00af"+ + "\u00ae\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u00af\3\2\2\2\u00b1\u00b2\3\2"+ + "\2\2\u00b2\u00b3\3\2\2\2\u00b3\u00b4\b\34\2\2\u00b48\3\2\2\2\22\2horu"+ + "{~\u0085\u0088\u008c\u0094\u0096\u009d\u009f\u00a4\u00b1\3\b\2\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.tokens b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.tokens index a91e170..88d248a 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.tokens +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathLexer.tokens @@ -31,7 +31,7 @@ WS=22 '.'=9 '[?('=10 ')]'=11 -'@.'=12 +'@'=12 '>'=13 '<'=14 '=='=15 diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathParser.java b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathParser.java index cbd930d..2a8f9ac 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathParser.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathParser.java @@ -23,20 +23,21 @@ public class JsonPathParser extends Parser { T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, COLON=16, AndOperator=17, OrOperator=18, NUM=19, QUOTED_STRING=20, KEY=21, WS=22; public static final int - RULE_path = 0, RULE_searchChild = 1, RULE_search = 2, RULE_anyChild = 3, - RULE_anyIndex = 4, RULE_any = 5, RULE_index = 6, RULE_indexes = 7, RULE_slicing = 8, - RULE_childNode = 9, RULE_childrenNode = 10, RULE_filter = 11, RULE_expr = 12, - RULE_exprExist = 13, RULE_exprGtNum = 14, RULE_exprLtNum = 15, RULE_exprEqualNum = 16, - RULE_exprEqualStr = 17; + RULE_path = 0, RULE_relativePath = 1, RULE_searchChild = 2, RULE_search = 3, + RULE_anyChild = 4, RULE_anyIndex = 5, RULE_any = 6, RULE_index = 7, RULE_indexes = 8, + RULE_slicing = 9, RULE_childNode = 10, RULE_childrenNode = 11, RULE_filter = 12, + RULE_filterExpr = 13, RULE_filterExist = 14, RULE_filterGtNum = 15, RULE_filterLtNum = 16, + RULE_filterEqualNum = 17, RULE_filterEqualStr = 18; public static final String[] ruleNames = { - "path", "searchChild", "search", "anyChild", "anyIndex", "any", "index", - "indexes", "slicing", "childNode", "childrenNode", "filter", "expr", "exprExist", - "exprGtNum", "exprLtNum", "exprEqualNum", "exprEqualStr" + "path", "relativePath", "searchChild", "search", "anyChild", "anyIndex", + "any", "index", "indexes", "slicing", "childNode", "childrenNode", "filter", + "filterExpr", "filterExist", "filterGtNum", "filterLtNum", "filterEqualNum", + "filterEqualStr" }; private static final String[] _LITERAL_NAMES = { null, "'$'", "'..'", "'.*'", "'[*]'", "'*'", "'['", "']'", "','", "'.'", - "'[?('", "')]'", "'@.'", "'>'", "'<'", "'=='", "':'", "'&&'", "'||'" + "'[?('", "')]'", "'@'", "'>'", "'<'", "'=='", "':'", "'&&'", "'||'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -94,65 +95,11 @@ public JsonPathParser(TokenStream input) { } public static class PathContext extends ParserRuleContext { public TerminalNode EOF() { return getToken(JsonPathParser.EOF, 0); } - public List searchChild() { - return getRuleContexts(SearchChildContext.class); + public List relativePath() { + return getRuleContexts(RelativePathContext.class); } - public SearchChildContext searchChild(int i) { - return getRuleContext(SearchChildContext.class,i); - } - public List search() { - return getRuleContexts(SearchContext.class); - } - public SearchContext search(int i) { - return getRuleContext(SearchContext.class,i); - } - public List index() { - return getRuleContexts(IndexContext.class); - } - public IndexContext index(int i) { - return getRuleContext(IndexContext.class,i); - } - public List indexes() { - return getRuleContexts(IndexesContext.class); - } - public IndexesContext indexes(int i) { - return getRuleContext(IndexesContext.class,i); - } - public List slicing() { - return getRuleContexts(SlicingContext.class); - } - public SlicingContext slicing(int i) { - return getRuleContext(SlicingContext.class,i); - } - public List childNode() { - return getRuleContexts(ChildNodeContext.class); - } - public ChildNodeContext childNode(int i) { - return getRuleContext(ChildNodeContext.class,i); - } - public List childrenNode() { - return getRuleContexts(ChildrenNodeContext.class); - } - public ChildrenNodeContext childrenNode(int i) { - return getRuleContext(ChildrenNodeContext.class,i); - } - public List anyChild() { - return getRuleContexts(AnyChildContext.class); - } - public AnyChildContext anyChild(int i) { - return getRuleContext(AnyChildContext.class,i); - } - public List anyIndex() { - return getRuleContexts(AnyIndexContext.class); - } - public AnyIndexContext anyIndex(int i) { - return getRuleContext(AnyIndexContext.class,i); - } - public List any() { - return getRuleContexts(AnyContext.class); - } - public AnyContext any(int i) { - return getRuleContext(AnyContext.class,i); + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); } public FilterContext filter() { return getRuleContext(FilterContext.class,0); @@ -175,93 +122,33 @@ public final PathContext path() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(36); + setState(38); match(T__0); - setState(49); + setState(42); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__8))) != 0)) { { - setState(47); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,0,_ctx) ) { - case 1: - { - setState(37); - searchChild(); - } - break; - case 2: - { - setState(38); - search(); - } - break; - case 3: - { - setState(39); - index(); - } - break; - case 4: - { - setState(40); - indexes(); - } - break; - case 5: - { - setState(41); - slicing(); - } - break; - case 6: - { - setState(42); - childNode(); - } - break; - case 7: - { - setState(43); - childrenNode(); - } - break; - case 8: - { - setState(44); - anyChild(); - } - break; - case 9: - { - setState(45); - anyIndex(); - } - break; - case 10: - { - setState(46); - any(); - } - break; + { + setState(39); + relativePath(); } } - setState(51); + setState(44); _errHandler.sync(this); _la = _input.LA(1); } - setState(53); + setState(46); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__9) { { - setState(52); + setState(45); filter(); } } - setState(55); + setState(48); match(EOF); } } @@ -276,6 +163,138 @@ public final PathContext path() throws RecognitionException { return _localctx; } + public static class RelativePathContext extends ParserRuleContext { + public SearchChildContext searchChild() { + return getRuleContext(SearchChildContext.class,0); + } + public SearchContext search() { + return getRuleContext(SearchContext.class,0); + } + public IndexContext index() { + return getRuleContext(IndexContext.class,0); + } + public IndexesContext indexes() { + return getRuleContext(IndexesContext.class,0); + } + public SlicingContext slicing() { + return getRuleContext(SlicingContext.class,0); + } + public ChildNodeContext childNode() { + return getRuleContext(ChildNodeContext.class,0); + } + public ChildrenNodeContext childrenNode() { + return getRuleContext(ChildrenNodeContext.class,0); + } + public AnyChildContext anyChild() { + return getRuleContext(AnyChildContext.class,0); + } + public AnyIndexContext anyIndex() { + return getRuleContext(AnyIndexContext.class,0); + } + public AnyContext any() { + return getRuleContext(AnyContext.class,0); + } + public RelativePathContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_relativePath; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitRelativePath(this); + else return visitor.visitChildren(this); + } + } + + public final RelativePathContext relativePath() throws RecognitionException { + RelativePathContext _localctx = new RelativePathContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_relativePath); + try { + setState(60); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(50); + searchChild(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(51); + search(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(52); + index(); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(53); + indexes(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(54); + slicing(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(55); + childNode(); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(56); + childrenNode(); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(57); + anyChild(); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(58); + anyIndex(); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(59); + any(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + public static class SearchChildContext extends ParserRuleContext { public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } public SearchChildContext(ParserRuleContext parent, int invokingState) { @@ -291,13 +310,13 @@ public T accept(ParseTreeVisitor visitor) { public final SearchChildContext searchChild() throws RecognitionException { SearchChildContext _localctx = new SearchChildContext(_ctx, getState()); - enterRule(_localctx, 2, RULE_searchChild); + enterRule(_localctx, 4, RULE_searchChild); try { enterOuterAlt(_localctx, 1); { - setState(57); + setState(62); match(T__1); - setState(58); + setState(63); match(KEY); } } @@ -326,11 +345,11 @@ public T accept(ParseTreeVisitor visitor) { public final SearchContext search() throws RecognitionException { SearchContext _localctx = new SearchContext(_ctx, getState()); - enterRule(_localctx, 4, RULE_search); + enterRule(_localctx, 6, RULE_search); try { enterOuterAlt(_localctx, 1); { - setState(60); + setState(65); match(T__1); } } @@ -359,11 +378,11 @@ public T accept(ParseTreeVisitor visitor) { public final AnyChildContext anyChild() throws RecognitionException { AnyChildContext _localctx = new AnyChildContext(_ctx, getState()); - enterRule(_localctx, 6, RULE_anyChild); + enterRule(_localctx, 8, RULE_anyChild); try { enterOuterAlt(_localctx, 1); { - setState(62); + setState(67); match(T__2); } } @@ -392,11 +411,11 @@ public T accept(ParseTreeVisitor visitor) { public final AnyIndexContext anyIndex() throws RecognitionException { AnyIndexContext _localctx = new AnyIndexContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_anyIndex); + enterRule(_localctx, 10, RULE_anyIndex); try { enterOuterAlt(_localctx, 1); { - setState(64); + setState(69); match(T__3); } } @@ -425,11 +444,11 @@ public T accept(ParseTreeVisitor visitor) { public final AnyContext any() throws RecognitionException { AnyContext _localctx = new AnyContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_any); + enterRule(_localctx, 12, RULE_any); try { enterOuterAlt(_localctx, 1); { - setState(66); + setState(71); match(T__4); } } @@ -459,15 +478,15 @@ public T accept(ParseTreeVisitor visitor) { public final IndexContext index() throws RecognitionException { IndexContext _localctx = new IndexContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_index); + enterRule(_localctx, 14, RULE_index); try { enterOuterAlt(_localctx, 1); { - setState(68); + setState(73); match(T__5); - setState(69); + setState(74); match(NUM); - setState(70); + setState(75); match(T__6); } } @@ -500,32 +519,32 @@ public T accept(ParseTreeVisitor visitor) { public final IndexesContext indexes() throws RecognitionException { IndexesContext _localctx = new IndexesContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_indexes); + enterRule(_localctx, 16, RULE_indexes); int _la; try { enterOuterAlt(_localctx, 1); { - setState(72); + setState(77); match(T__5); - setState(73); - match(NUM); setState(78); + match(NUM); + setState(83); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__7) { { { - setState(74); + setState(79); match(T__7); - setState(75); + setState(80); match(NUM); } } - setState(80); + setState(85); _errHandler.sync(this); _la = _input.LA(1); } - setState(81); + setState(86); match(T__6); } } @@ -559,36 +578,36 @@ public T accept(ParseTreeVisitor visitor) { public final SlicingContext slicing() throws RecognitionException { SlicingContext _localctx = new SlicingContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_slicing); + enterRule(_localctx, 18, RULE_slicing); int _la; try { enterOuterAlt(_localctx, 1); { - setState(83); + setState(88); match(T__5); - setState(85); + setState(90); _errHandler.sync(this); _la = _input.LA(1); if (_la==NUM) { { - setState(84); + setState(89); match(NUM); } } - setState(87); + setState(92); match(COLON); - setState(89); + setState(94); _errHandler.sync(this); _la = _input.LA(1); if (_la==NUM) { { - setState(88); + setState(93); match(NUM); } } - setState(91); + setState(96); match(T__6); } } @@ -618,13 +637,13 @@ public T accept(ParseTreeVisitor visitor) { public final ChildNodeContext childNode() throws RecognitionException { ChildNodeContext _localctx = new ChildNodeContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_childNode); + enterRule(_localctx, 20, RULE_childNode); try { enterOuterAlt(_localctx, 1); { - setState(93); + setState(98); match(T__8); - setState(94); + setState(99); match(KEY); } } @@ -657,32 +676,32 @@ public T accept(ParseTreeVisitor visitor) { public final ChildrenNodeContext childrenNode() throws RecognitionException { ChildrenNodeContext _localctx = new ChildrenNodeContext(_ctx, getState()); - enterRule(_localctx, 20, RULE_childrenNode); + enterRule(_localctx, 22, RULE_childrenNode); int _la; try { enterOuterAlt(_localctx, 1); { - setState(96); + setState(101); match(T__5); - setState(97); - match(QUOTED_STRING); setState(102); + match(QUOTED_STRING); + setState(107); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__7) { { { - setState(98); + setState(103); match(T__7); - setState(99); + setState(104); match(QUOTED_STRING); } } - setState(104); + setState(109); _errHandler.sync(this); _la = _input.LA(1); } - setState(105); + setState(110); match(T__6); } } @@ -698,8 +717,8 @@ public final ChildrenNodeContext childrenNode() throws RecognitionException { } public static class FilterContext extends ParserRuleContext { - public ExprContext expr() { - return getRuleContext(ExprContext.class,0); + public FilterExprContext filterExpr() { + return getRuleContext(FilterExprContext.class,0); } public FilterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); @@ -714,15 +733,15 @@ public T accept(ParseTreeVisitor visitor) { public final FilterContext filter() throws RecognitionException { FilterContext _localctx = new FilterContext(_ctx, getState()); - enterRule(_localctx, 22, RULE_filter); + enterRule(_localctx, 24, RULE_filter); try { enterOuterAlt(_localctx, 1); { - setState(107); + setState(112); match(T__9); - setState(108); - expr(0); - setState(109); + setState(113); + filterExpr(0); + setState(114); match(T__10); } } @@ -737,92 +756,92 @@ public final FilterContext filter() throws RecognitionException { return _localctx; } - public static class ExprContext extends ParserRuleContext { - public ExprEqualNumContext exprEqualNum() { - return getRuleContext(ExprEqualNumContext.class,0); + public static class FilterExprContext extends ParserRuleContext { + public FilterEqualNumContext filterEqualNum() { + return getRuleContext(FilterEqualNumContext.class,0); } - public ExprEqualStrContext exprEqualStr() { - return getRuleContext(ExprEqualStrContext.class,0); + public FilterEqualStrContext filterEqualStr() { + return getRuleContext(FilterEqualStrContext.class,0); } - public ExprGtNumContext exprGtNum() { - return getRuleContext(ExprGtNumContext.class,0); + public FilterGtNumContext filterGtNum() { + return getRuleContext(FilterGtNumContext.class,0); } - public ExprLtNumContext exprLtNum() { - return getRuleContext(ExprLtNumContext.class,0); + public FilterLtNumContext filterLtNum() { + return getRuleContext(FilterLtNumContext.class,0); } - public ExprExistContext exprExist() { - return getRuleContext(ExprExistContext.class,0); + public FilterExistContext filterExist() { + return getRuleContext(FilterExistContext.class,0); } - public List expr() { - return getRuleContexts(ExprContext.class); + public List filterExpr() { + return getRuleContexts(FilterExprContext.class); } - public ExprContext expr(int i) { - return getRuleContext(ExprContext.class,i); + public FilterExprContext filterExpr(int i) { + return getRuleContext(FilterExprContext.class,i); } public TerminalNode AndOperator() { return getToken(JsonPathParser.AndOperator, 0); } public TerminalNode OrOperator() { return getToken(JsonPathParser.OrOperator, 0); } - public ExprContext(ParserRuleContext parent, int invokingState) { + public FilterExprContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_expr; } + @Override public int getRuleIndex() { return RULE_filterExpr; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExpr(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterExpr(this); else return visitor.visitChildren(this); } } - public final ExprContext expr() throws RecognitionException { - return expr(0); + public final FilterExprContext filterExpr() throws RecognitionException { + return filterExpr(0); } - private ExprContext expr(int _p) throws RecognitionException { + private FilterExprContext filterExpr(int _p) throws RecognitionException { ParserRuleContext _parentctx = _ctx; int _parentState = getState(); - ExprContext _localctx = new ExprContext(_ctx, _parentState); - ExprContext _prevctx = _localctx; - int _startState = 24; - enterRecursionRule(_localctx, 24, RULE_expr, _p); + FilterExprContext _localctx = new FilterExprContext(_ctx, _parentState); + FilterExprContext _prevctx = _localctx; + int _startState = 26; + enterRecursionRule(_localctx, 26, RULE_filterExpr, _p); try { int _alt; enterOuterAlt(_localctx, 1); { - setState(117); + setState(122); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { case 1: { - setState(112); - exprEqualNum(); + setState(117); + filterEqualNum(); } break; case 2: { - setState(113); - exprEqualStr(); + setState(118); + filterEqualStr(); } break; case 3: { - setState(114); - exprGtNum(); + setState(119); + filterGtNum(); } break; case 4: { - setState(115); - exprLtNum(); + setState(120); + filterLtNum(); } break; case 5: { - setState(116); - exprExist(); + setState(121); + filterExist(); } break; } _ctx.stop = _input.LT(-1); - setState(127); + setState(132); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,9,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -830,37 +849,37 @@ private ExprContext expr(int _p) throws RecognitionException { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(125); + setState(130); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { case 1: { - _localctx = new ExprContext(_parentctx, _parentState); - pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(119); + _localctx = new FilterExprContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_filterExpr); + setState(124); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(120); + setState(125); match(AndOperator); - setState(121); - expr(8); + setState(126); + filterExpr(8); } break; case 2: { - _localctx = new ExprContext(_parentctx, _parentState); - pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(122); + _localctx = new FilterExprContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_filterExpr); + setState(127); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(123); + setState(128); match(OrOperator); - setState(124); - expr(7); + setState(129); + filterExpr(7); } break; } } } - setState(129); + setState(134); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,9,_ctx); } @@ -877,29 +896,53 @@ private ExprContext expr(int _p) throws RecognitionException { return _localctx; } - public static class ExprExistContext extends ParserRuleContext { - public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } - public ExprExistContext(ParserRuleContext parent, int invokingState) { + public static class FilterExistContext extends ParserRuleContext { + public List relativePath() { + return getRuleContexts(RelativePathContext.class); + } + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); + } + public FilterExistContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_exprExist; } + @Override public int getRuleIndex() { return RULE_filterExist; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExprExist(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterExist(this); else return visitor.visitChildren(this); } } - public final ExprExistContext exprExist() throws RecognitionException { - ExprExistContext _localctx = new ExprExistContext(_ctx, getState()); - enterRule(_localctx, 26, RULE_exprExist); + public final FilterExistContext filterExist() throws RecognitionException { + FilterExistContext _localctx = new FilterExistContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_filterExist); try { + int _alt; enterOuterAlt(_localctx, 1); { - setState(130); + setState(135); match(T__11); - setState(131); - match(KEY); + setState(137); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(136); + relativePath(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(139); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,10,_ctx); + } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); } } catch (RecognitionException re) { @@ -913,33 +956,51 @@ public final ExprExistContext exprExist() throws RecognitionException { return _localctx; } - public static class ExprGtNumContext extends ParserRuleContext { - public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } + public static class FilterGtNumContext extends ParserRuleContext { public TerminalNode NUM() { return getToken(JsonPathParser.NUM, 0); } - public ExprGtNumContext(ParserRuleContext parent, int invokingState) { + public List relativePath() { + return getRuleContexts(RelativePathContext.class); + } + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); + } + public FilterGtNumContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_exprGtNum; } + @Override public int getRuleIndex() { return RULE_filterGtNum; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExprGtNum(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterGtNum(this); else return visitor.visitChildren(this); } } - public final ExprGtNumContext exprGtNum() throws RecognitionException { - ExprGtNumContext _localctx = new ExprGtNumContext(_ctx, getState()); - enterRule(_localctx, 28, RULE_exprGtNum); + public final FilterGtNumContext filterGtNum() throws RecognitionException { + FilterGtNumContext _localctx = new FilterGtNumContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_filterGtNum); + int _la; try { enterOuterAlt(_localctx, 1); { - setState(133); + setState(141); match(T__11); - setState(134); - match(KEY); - setState(135); + setState(143); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(142); + relativePath(); + } + } + setState(145); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__8))) != 0) ); + setState(147); match(T__12); - setState(136); + setState(148); match(NUM); } } @@ -954,33 +1015,51 @@ public final ExprGtNumContext exprGtNum() throws RecognitionException { return _localctx; } - public static class ExprLtNumContext extends ParserRuleContext { - public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } + public static class FilterLtNumContext extends ParserRuleContext { public TerminalNode NUM() { return getToken(JsonPathParser.NUM, 0); } - public ExprLtNumContext(ParserRuleContext parent, int invokingState) { + public List relativePath() { + return getRuleContexts(RelativePathContext.class); + } + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); + } + public FilterLtNumContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_exprLtNum; } + @Override public int getRuleIndex() { return RULE_filterLtNum; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExprLtNum(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterLtNum(this); else return visitor.visitChildren(this); } } - public final ExprLtNumContext exprLtNum() throws RecognitionException { - ExprLtNumContext _localctx = new ExprLtNumContext(_ctx, getState()); - enterRule(_localctx, 30, RULE_exprLtNum); + public final FilterLtNumContext filterLtNum() throws RecognitionException { + FilterLtNumContext _localctx = new FilterLtNumContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_filterLtNum); + int _la; try { enterOuterAlt(_localctx, 1); { - setState(138); + setState(150); match(T__11); - setState(139); - match(KEY); - setState(140); + setState(152); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(151); + relativePath(); + } + } + setState(154); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__8))) != 0) ); + setState(156); match(T__13); - setState(141); + setState(157); match(NUM); } } @@ -995,33 +1074,51 @@ public final ExprLtNumContext exprLtNum() throws RecognitionException { return _localctx; } - public static class ExprEqualNumContext extends ParserRuleContext { - public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } + public static class FilterEqualNumContext extends ParserRuleContext { public TerminalNode NUM() { return getToken(JsonPathParser.NUM, 0); } - public ExprEqualNumContext(ParserRuleContext parent, int invokingState) { + public List relativePath() { + return getRuleContexts(RelativePathContext.class); + } + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); + } + public FilterEqualNumContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_exprEqualNum; } + @Override public int getRuleIndex() { return RULE_filterEqualNum; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExprEqualNum(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterEqualNum(this); else return visitor.visitChildren(this); } } - public final ExprEqualNumContext exprEqualNum() throws RecognitionException { - ExprEqualNumContext _localctx = new ExprEqualNumContext(_ctx, getState()); - enterRule(_localctx, 32, RULE_exprEqualNum); + public final FilterEqualNumContext filterEqualNum() throws RecognitionException { + FilterEqualNumContext _localctx = new FilterEqualNumContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_filterEqualNum); + int _la; try { enterOuterAlt(_localctx, 1); { - setState(143); + setState(159); match(T__11); - setState(144); - match(KEY); - setState(145); + setState(161); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(160); + relativePath(); + } + } + setState(163); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__8))) != 0) ); + setState(165); match(T__14); - setState(146); + setState(166); match(NUM); } } @@ -1036,33 +1133,51 @@ public final ExprEqualNumContext exprEqualNum() throws RecognitionException { return _localctx; } - public static class ExprEqualStrContext extends ParserRuleContext { - public TerminalNode KEY() { return getToken(JsonPathParser.KEY, 0); } + public static class FilterEqualStrContext extends ParserRuleContext { public TerminalNode QUOTED_STRING() { return getToken(JsonPathParser.QUOTED_STRING, 0); } - public ExprEqualStrContext(ParserRuleContext parent, int invokingState) { + public List relativePath() { + return getRuleContexts(RelativePathContext.class); + } + public RelativePathContext relativePath(int i) { + return getRuleContext(RelativePathContext.class,i); + } + public FilterEqualStrContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_exprEqualStr; } + @Override public int getRuleIndex() { return RULE_filterEqualStr; } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitExprEqualStr(this); + if ( visitor instanceof JsonPathVisitor ) return ((JsonPathVisitor)visitor).visitFilterEqualStr(this); else return visitor.visitChildren(this); } } - public final ExprEqualStrContext exprEqualStr() throws RecognitionException { - ExprEqualStrContext _localctx = new ExprEqualStrContext(_ctx, getState()); - enterRule(_localctx, 34, RULE_exprEqualStr); + public final FilterEqualStrContext filterEqualStr() throws RecognitionException { + FilterEqualStrContext _localctx = new FilterEqualStrContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_filterEqualStr); + int _la; try { enterOuterAlt(_localctx, 1); { - setState(148); + setState(168); match(T__11); - setState(149); - match(KEY); - setState(150); + setState(170); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(169); + relativePath(); + } + } + setState(172); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__8))) != 0) ); + setState(174); match(T__14); - setState(151); + setState(175); match(QUOTED_STRING); } } @@ -1079,12 +1194,12 @@ public final ExprEqualStrContext exprEqualStr() throws RecognitionException { public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { switch (ruleIndex) { - case 12: - return expr_sempred((ExprContext)_localctx, predIndex); + case 13: + return filterExpr_sempred((FilterExprContext)_localctx, predIndex); } return true; } - private boolean expr_sempred(ExprContext _localctx, int predIndex) { + private boolean filterExpr_sempred(FilterExprContext _localctx, int predIndex) { switch (predIndex) { case 0: return precpred(_ctx, 7); @@ -1095,48 +1210,59 @@ private boolean expr_sempred(ExprContext _localctx, int predIndex) { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\30\u009c\4\2\t\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\30\u00b4\4\2\t\2"+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ - "\4\23\t\23\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\7\2\62\n\2\f\2"+ - "\16\2\65\13\2\3\2\5\28\n\2\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6"+ - "\3\7\3\7\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\7\tO\n\t\f\t\16\tR\13\t\3\t\3"+ - "\t\3\n\3\n\5\nX\n\n\3\n\3\n\5\n\\\n\n\3\n\3\n\3\13\3\13\3\13\3\f\3\f\3"+ - "\f\3\f\7\fg\n\f\f\f\16\fj\13\f\3\f\3\f\3\r\3\r\3\r\3\r\3\16\3\16\3\16"+ - "\3\16\3\16\3\16\5\16x\n\16\3\16\3\16\3\16\3\16\3\16\3\16\7\16\u0080\n"+ - "\16\f\16\16\16\u0083\13\16\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\21"+ - "\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23"+ - "\3\23\2\3\32\24\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$\2\2\2\u009e"+ - "\2&\3\2\2\2\4;\3\2\2\2\6>\3\2\2\2\b@\3\2\2\2\nB\3\2\2\2\fD\3\2\2\2\16"+ - "F\3\2\2\2\20J\3\2\2\2\22U\3\2\2\2\24_\3\2\2\2\26b\3\2\2\2\30m\3\2\2\2"+ - "\32w\3\2\2\2\34\u0084\3\2\2\2\36\u0087\3\2\2\2 \u008c\3\2\2\2\"\u0091"+ - "\3\2\2\2$\u0096\3\2\2\2&\63\7\3\2\2\'\62\5\4\3\2(\62\5\6\4\2)\62\5\16"+ - "\b\2*\62\5\20\t\2+\62\5\22\n\2,\62\5\24\13\2-\62\5\26\f\2.\62\5\b\5\2"+ - "/\62\5\n\6\2\60\62\5\f\7\2\61\'\3\2\2\2\61(\3\2\2\2\61)\3\2\2\2\61*\3"+ - "\2\2\2\61+\3\2\2\2\61,\3\2\2\2\61-\3\2\2\2\61.\3\2\2\2\61/\3\2\2\2\61"+ - "\60\3\2\2\2\62\65\3\2\2\2\63\61\3\2\2\2\63\64\3\2\2\2\64\67\3\2\2\2\65"+ - "\63\3\2\2\2\668\5\30\r\2\67\66\3\2\2\2\678\3\2\2\289\3\2\2\29:\7\2\2\3"+ - ":\3\3\2\2\2;<\7\4\2\2<=\7\27\2\2=\5\3\2\2\2>?\7\4\2\2?\7\3\2\2\2@A\7\5"+ - "\2\2A\t\3\2\2\2BC\7\6\2\2C\13\3\2\2\2DE\7\7\2\2E\r\3\2\2\2FG\7\b\2\2G"+ - "H\7\25\2\2HI\7\t\2\2I\17\3\2\2\2JK\7\b\2\2KP\7\25\2\2LM\7\n\2\2MO\7\25"+ - "\2\2NL\3\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2QS\3\2\2\2RP\3\2\2\2ST\7\t"+ - "\2\2T\21\3\2\2\2UW\7\b\2\2VX\7\25\2\2WV\3\2\2\2WX\3\2\2\2XY\3\2\2\2Y["+ - "\7\22\2\2Z\\\7\25\2\2[Z\3\2\2\2[\\\3\2\2\2\\]\3\2\2\2]^\7\t\2\2^\23\3"+ - "\2\2\2_`\7\13\2\2`a\7\27\2\2a\25\3\2\2\2bc\7\b\2\2ch\7\26\2\2de\7\n\2"+ - "\2eg\7\26\2\2fd\3\2\2\2gj\3\2\2\2hf\3\2\2\2hi\3\2\2\2ik\3\2\2\2jh\3\2"+ - "\2\2kl\7\t\2\2l\27\3\2\2\2mn\7\f\2\2no\5\32\16\2op\7\r\2\2p\31\3\2\2\2"+ - "qr\b\16\1\2rx\5\"\22\2sx\5$\23\2tx\5\36\20\2ux\5 \21\2vx\5\34\17\2wq\3"+ - "\2\2\2ws\3\2\2\2wt\3\2\2\2wu\3\2\2\2wv\3\2\2\2x\u0081\3\2\2\2yz\f\t\2"+ - "\2z{\7\23\2\2{\u0080\5\32\16\n|}\f\b\2\2}~\7\24\2\2~\u0080\5\32\16\t\177"+ - "y\3\2\2\2\177|\3\2\2\2\u0080\u0083\3\2\2\2\u0081\177\3\2\2\2\u0081\u0082"+ - "\3\2\2\2\u0082\33\3\2\2\2\u0083\u0081\3\2\2\2\u0084\u0085\7\16\2\2\u0085"+ - "\u0086\7\27\2\2\u0086\35\3\2\2\2\u0087\u0088\7\16\2\2\u0088\u0089\7\27"+ - "\2\2\u0089\u008a\7\17\2\2\u008a\u008b\7\25\2\2\u008b\37\3\2\2\2\u008c"+ - "\u008d\7\16\2\2\u008d\u008e\7\27\2\2\u008e\u008f\7\20\2\2\u008f\u0090"+ - "\7\25\2\2\u0090!\3\2\2\2\u0091\u0092\7\16\2\2\u0092\u0093\7\27\2\2\u0093"+ - "\u0094\7\21\2\2\u0094\u0095\7\25\2\2\u0095#\3\2\2\2\u0096\u0097\7\16\2"+ - "\2\u0097\u0098\7\27\2\2\u0098\u0099\7\21\2\2\u0099\u009a\7\26\2\2\u009a"+ - "%\3\2\2\2\f\61\63\67PW[hw\177\u0081"; + "\4\23\t\23\4\24\t\24\3\2\3\2\7\2+\n\2\f\2\16\2.\13\2\3\2\5\2\61\n\2\3"+ + "\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3?\n\3\3\4\3\4\3\4\3"+ + "\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\7\nT\n"+ + "\n\f\n\16\nW\13\n\3\n\3\n\3\13\3\13\5\13]\n\13\3\13\3\13\5\13a\n\13\3"+ + "\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\r\7\rl\n\r\f\r\16\ro\13\r\3\r\3\r\3"+ + "\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\5\17}\n\17\3\17\3\17"+ + "\3\17\3\17\3\17\3\17\7\17\u0085\n\17\f\17\16\17\u0088\13\17\3\20\3\20"+ + "\6\20\u008c\n\20\r\20\16\20\u008d\3\21\3\21\6\21\u0092\n\21\r\21\16\21"+ + "\u0093\3\21\3\21\3\21\3\22\3\22\6\22\u009b\n\22\r\22\16\22\u009c\3\22"+ + "\3\22\3\22\3\23\3\23\6\23\u00a4\n\23\r\23\16\23\u00a5\3\23\3\23\3\23\3"+ + "\24\3\24\6\24\u00ad\n\24\r\24\16\24\u00ae\3\24\3\24\3\24\3\24\2\3\34\25"+ + "\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&\2\2\2\u00ba\2(\3\2\2\2\4"+ + ">\3\2\2\2\6@\3\2\2\2\bC\3\2\2\2\nE\3\2\2\2\fG\3\2\2\2\16I\3\2\2\2\20K"+ + "\3\2\2\2\22O\3\2\2\2\24Z\3\2\2\2\26d\3\2\2\2\30g\3\2\2\2\32r\3\2\2\2\34"+ + "|\3\2\2\2\36\u0089\3\2\2\2 \u008f\3\2\2\2\"\u0098\3\2\2\2$\u00a1\3\2\2"+ + "\2&\u00aa\3\2\2\2(,\7\3\2\2)+\5\4\3\2*)\3\2\2\2+.\3\2\2\2,*\3\2\2\2,-"+ + "\3\2\2\2-\60\3\2\2\2.,\3\2\2\2/\61\5\32\16\2\60/\3\2\2\2\60\61\3\2\2\2"+ + "\61\62\3\2\2\2\62\63\7\2\2\3\63\3\3\2\2\2\64?\5\6\4\2\65?\5\b\5\2\66?"+ + "\5\20\t\2\67?\5\22\n\28?\5\24\13\29?\5\26\f\2:?\5\30\r\2;?\5\n\6\2\64\3\2\2\2>\65\3\2\2\2>\66\3\2\2\2>\67\3\2\2\2>8\3"+ + "\2\2\2>9\3\2\2\2>:\3\2\2\2>;\3\2\2\2><\3\2\2\2>=\3\2\2\2?\5\3\2\2\2@A"+ + "\7\4\2\2AB\7\27\2\2B\7\3\2\2\2CD\7\4\2\2D\t\3\2\2\2EF\7\5\2\2F\13\3\2"+ + "\2\2GH\7\6\2\2H\r\3\2\2\2IJ\7\7\2\2J\17\3\2\2\2KL\7\b\2\2LM\7\25\2\2M"+ + "N\7\t\2\2N\21\3\2\2\2OP\7\b\2\2PU\7\25\2\2QR\7\n\2\2RT\7\25\2\2SQ\3\2"+ + "\2\2TW\3\2\2\2US\3\2\2\2UV\3\2\2\2VX\3\2\2\2WU\3\2\2\2XY\7\t\2\2Y\23\3"+ + "\2\2\2Z\\\7\b\2\2[]\7\25\2\2\\[\3\2\2\2\\]\3\2\2\2]^\3\2\2\2^`\7\22\2"+ + "\2_a\7\25\2\2`_\3\2\2\2`a\3\2\2\2ab\3\2\2\2bc\7\t\2\2c\25\3\2\2\2de\7"+ + "\13\2\2ef\7\27\2\2f\27\3\2\2\2gh\7\b\2\2hm\7\26\2\2ij\7\n\2\2jl\7\26\2"+ + "\2ki\3\2\2\2lo\3\2\2\2mk\3\2\2\2mn\3\2\2\2np\3\2\2\2om\3\2\2\2pq\7\t\2"+ + "\2q\31\3\2\2\2rs\7\f\2\2st\5\34\17\2tu\7\r\2\2u\33\3\2\2\2vw\b\17\1\2"+ + "w}\5$\23\2x}\5&\24\2y}\5 \21\2z}\5\"\22\2{}\5\36\20\2|v\3\2\2\2|x\3\2"+ + "\2\2|y\3\2\2\2|z\3\2\2\2|{\3\2\2\2}\u0086\3\2\2\2~\177\f\t\2\2\177\u0080"+ + "\7\23\2\2\u0080\u0085\5\34\17\n\u0081\u0082\f\b\2\2\u0082\u0083\7\24\2"+ + "\2\u0083\u0085\5\34\17\t\u0084~\3\2\2\2\u0084\u0081\3\2\2\2\u0085\u0088"+ + "\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0087\3\2\2\2\u0087\35\3\2\2\2\u0088"+ + "\u0086\3\2\2\2\u0089\u008b\7\16\2\2\u008a\u008c\5\4\3\2\u008b\u008a\3"+ + "\2\2\2\u008c\u008d\3\2\2\2\u008d\u008b\3\2\2\2\u008d\u008e\3\2\2\2\u008e"+ + "\37\3\2\2\2\u008f\u0091\7\16\2\2\u0090\u0092\5\4\3\2\u0091\u0090\3\2\2"+ + "\2\u0092\u0093\3\2\2\2\u0093\u0091\3\2\2\2\u0093\u0094\3\2\2\2\u0094\u0095"+ + "\3\2\2\2\u0095\u0096\7\17\2\2\u0096\u0097\7\25\2\2\u0097!\3\2\2\2\u0098"+ + "\u009a\7\16\2\2\u0099\u009b\5\4\3\2\u009a\u0099\3\2\2\2\u009b\u009c\3"+ + "\2\2\2\u009c\u009a\3\2\2\2\u009c\u009d\3\2\2\2\u009d\u009e\3\2\2\2\u009e"+ + "\u009f\7\20\2\2\u009f\u00a0\7\25\2\2\u00a0#\3\2\2\2\u00a1\u00a3\7\16\2"+ + "\2\u00a2\u00a4\5\4\3\2\u00a3\u00a2\3\2\2\2\u00a4\u00a5\3\2\2\2\u00a5\u00a3"+ + "\3\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00a8\7\21\2\2"+ + "\u00a8\u00a9\7\25\2\2\u00a9%\3\2\2\2\u00aa\u00ac\7\16\2\2\u00ab\u00ad"+ + "\5\4\3\2\u00ac\u00ab\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae\u00ac\3\2\2\2\u00ae"+ + "\u00af\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\7\21\2\2\u00b1\u00b2\7"+ + "\26\2\2\u00b2\'\3\2\2\2\21,\60>U\\`m|\u0084\u0086\u008d\u0093\u009c\u00a5"+ + "\u00ae"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathVisitor.java b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathVisitor.java index 40db4c7..6609fd6 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathVisitor.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/compiler/JsonPathVisitor.java @@ -18,6 +18,12 @@ public interface JsonPathVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitPath(JsonPathParser.PathContext ctx); + /** + * Visit a parse tree produced by {@link JsonPathParser#relativePath}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelativePath(JsonPathParser.RelativePathContext ctx); /** * Visit a parse tree produced by {@link JsonPathParser#searchChild}. * @param ctx the parse tree @@ -85,39 +91,39 @@ public interface JsonPathVisitor extends ParseTreeVisitor { */ T visitFilter(JsonPathParser.FilterContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#expr}. + * Visit a parse tree produced by {@link JsonPathParser#filterExpr}. * @param ctx the parse tree * @return the visitor result */ - T visitExpr(JsonPathParser.ExprContext ctx); + T visitFilterExpr(JsonPathParser.FilterExprContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#exprExist}. + * Visit a parse tree produced by {@link JsonPathParser#filterExist}. * @param ctx the parse tree * @return the visitor result */ - T visitExprExist(JsonPathParser.ExprExistContext ctx); + T visitFilterExist(JsonPathParser.FilterExistContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#exprGtNum}. + * Visit a parse tree produced by {@link JsonPathParser#filterGtNum}. * @param ctx the parse tree * @return the visitor result */ - T visitExprGtNum(JsonPathParser.ExprGtNumContext ctx); + T visitFilterGtNum(JsonPathParser.FilterGtNumContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#exprLtNum}. + * Visit a parse tree produced by {@link JsonPathParser#filterLtNum}. * @param ctx the parse tree * @return the visitor result */ - T visitExprLtNum(JsonPathParser.ExprLtNumContext ctx); + T visitFilterLtNum(JsonPathParser.FilterLtNumContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#exprEqualNum}. + * Visit a parse tree produced by {@link JsonPathParser#filterEqualNum}. * @param ctx the parse tree * @return the visitor result */ - T visitExprEqualNum(JsonPathParser.ExprEqualNumContext ctx); + T visitFilterEqualNum(JsonPathParser.FilterEqualNumContext ctx); /** - * Visit a parse tree produced by {@link JsonPathParser#exprEqualStr}. + * Visit a parse tree produced by {@link JsonPathParser#filterEqualStr}. * @param ctx the parse tree * @return the visitor result */ - T visitExprEqualStr(JsonPathParser.ExprEqualStrContext ctx); + T visitFilterEqualStr(JsonPathParser.FilterEqualStrContext ctx); } \ No newline at end of file diff --git a/jsurfer-core/src/main/java/org/jsfr/json/path/JsonPath.java b/jsurfer-core/src/main/java/org/jsfr/json/path/JsonPath.java index 8d3da93..4fd7a49 100644 --- a/jsurfer-core/src/main/java/org/jsfr/json/path/JsonPath.java +++ b/jsurfer-core/src/main/java/org/jsfr/json/path/JsonPath.java @@ -171,6 +171,9 @@ public Object resolve(Object document, DocumentResolver resolver) { } Object current = document; for (PathOperator pathOperator : this) { + if (current == null) { + return null; + } current = pathOperator.resolve(current, resolver); } return current; diff --git a/jsurfer-core/src/main/resources/JsonPath.g4 b/jsurfer-core/src/main/resources/JsonPath.g4 index 3e87839..3cacf09 100644 --- a/jsurfer-core/src/main/resources/JsonPath.g4 +++ b/jsurfer-core/src/main/resources/JsonPath.g4 @@ -4,7 +4,8 @@ grammar JsonPath; package org.jsfr.json.compiler; } -path: '$' (searchChild|search|index|indexes|slicing|childNode|childrenNode|anyChild|anyIndex|any)* filter? EOF; +path: '$' relativePath* filter? EOF; +relativePath: searchChild|search|index|indexes|slicing|childNode|childrenNode|anyChild|anyIndex|any; searchChild: '..' KEY; search: '..' ; anyChild: '.*' ; @@ -16,20 +17,20 @@ slicing: '[' NUM? COLON NUM? ']'; COLON : ':'; childNode: '.' KEY ; childrenNode: '[' QUOTED_STRING ( ',' QUOTED_STRING )* ']' ; -filter: '[?(' expr ')]'; -expr : expr AndOperator expr - | expr OrOperator expr - | exprEqualNum - | exprEqualStr - | exprGtNum - | exprLtNum - | exprExist +filter: '[?(' filterExpr ')]'; +filterExpr : filterExpr AndOperator filterExpr + | filterExpr OrOperator filterExpr + | filterEqualNum + | filterEqualStr + | filterGtNum + | filterLtNum + | filterExist ; -exprExist: '@.' KEY; -exprGtNum: '@.' KEY '>' NUM; -exprLtNum: '@.' KEY '<' NUM; -exprEqualNum: '@.' KEY '==' NUM; -exprEqualStr: '@.' KEY '==' QUOTED_STRING; +filterExist: '@' relativePath+; +filterGtNum: '@' relativePath+ '>' NUM; +filterLtNum: '@' relativePath+ '<' NUM; +filterEqualNum: '@' relativePath+ '==' NUM; +filterEqualStr: '@' relativePath+ '==' QUOTED_STRING; //exprArrayIdx: '@.length-' NUM; AndOperator: '&&'; OrOperator: '||'; diff --git a/jsurfer-fastjson/pom.xml b/jsurfer-fastjson/pom.xml index 800f5a6..b2b5f95 100644 --- a/jsurfer-fastjson/pom.xml +++ b/jsurfer-fastjson/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-fastjson/src/main/java/org/jsfr/json/provider/FastJsonProvider.java b/jsurfer-fastjson/src/main/java/org/jsfr/json/provider/FastJsonProvider.java index fc229e9..d3c7d86 100644 --- a/jsurfer-fastjson/src/main/java/org/jsfr/json/provider/FastJsonProvider.java +++ b/jsurfer-fastjson/src/main/java/org/jsfr/json/provider/FastJsonProvider.java @@ -1,5 +1,6 @@ package org.jsfr.json.provider; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -74,7 +75,11 @@ public Object primitiveNull() { @Override public T cast(Object value, Class tClass) { - return tClass.cast(value); + if (value instanceof JSON) { + return JSON.toJavaObject((JSON) value, tClass); + } else { + return tClass.cast(value); + } } } diff --git a/jsurfer-gson/pom.xml b/jsurfer-gson/pom.xml index 4ffb5d7..ae25348 100644 --- a/jsurfer-gson/pom.xml +++ b/jsurfer-gson/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-jackson/pom.xml b/jsurfer-jackson/pom.xml index 371c8a9..7ed695f 100644 --- a/jsurfer-jackson/pom.xml +++ b/jsurfer-jackson/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/jsurfer-jsonsimple/pom.xml b/jsurfer-jsonsimple/pom.xml index 7a415b6..63915c8 100644 --- a/jsurfer-jsonsimple/pom.xml +++ b/jsurfer-jsonsimple/pom.xml @@ -5,7 +5,7 @@ jsurfer com.github.jsurfer - 1.4 + 1.4.1 4.0.0 diff --git a/pom.xml b/pom.xml index 9b1db3d..17d6502 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.github.jsurfer jsurfer - 1.4 + 1.4.1 pom JsonSurfer Let's surf on json