2 changed files with 230 additions and 155 deletions
@ -1,77 +1,77 @@
|
||||
package com.jayway.jsonpath.internal.function.text; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.GsonBuilder; |
||||
import com.jayway.jsonpath.internal.EvaluationContext; |
||||
import com.jayway.jsonpath.internal.Path; |
||||
import com.jayway.jsonpath.internal.PathRef; |
||||
import com.jayway.jsonpath.internal.function.Parameter; |
||||
import com.jayway.jsonpath.internal.function.PathFunction; |
||||
import com.jayway.jsonpath.internal.path.CompiledPath; |
||||
import com.jayway.jsonpath.internal.path.PathToken; |
||||
import com.jayway.jsonpath.internal.path.RootPathToken; |
||||
import com.jayway.jsonpath.internal.path.WildcardPathToken; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Provides the length of a JSONArray Object |
||||
* |
||||
* Created by mattg on 6/26/15. |
||||
*/ |
||||
public class Length implements PathFunction { |
||||
|
||||
public static final String TOKEN_NAME = "length"; |
||||
|
||||
/** |
||||
* When we calculate the length of a path, what we're asking is given the node we land on how many children does it |
||||
* have. Thus when we wrote the original query what we really wanted was $..book.length() or $.length($..book.*) |
||||
* |
||||
* @param currentPath |
||||
* The current path location inclusive of the function name |
||||
* @param parent |
||||
* The path location above the current function |
||||
* |
||||
* @param model |
||||
* The JSON model as input to this particular function |
||||
* |
||||
* @param ctx |
||||
* Eval context, state bag used as the path is traversed, maintains the result of executing |
||||
* |
||||
* @param parameters |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) { |
||||
if (null != parameters && parameters.size() > 0) { |
||||
|
||||
// Set the tail of the first parameter, when its not a function path parameter (which wouldn't make sense
|
||||
// for length - to the wildcard such that we request all of its children so we can get back an array and
|
||||
// take its length.
|
||||
Parameter lengthOfParameter = parameters.get(0); |
||||
if (!lengthOfParameter.getPath().isFunctionPath()) { |
||||
Path path = lengthOfParameter.getPath(); |
||||
if (path instanceof CompiledPath) { |
||||
RootPathToken root = ((CompiledPath) path).getRoot(); |
||||
PathToken tail = root.getNext(); |
||||
while (null != tail && null != tail.getNext()) { |
||||
tail = tail.getNext(); |
||||
} |
||||
if (null != tail) { |
||||
tail.setNext(new WildcardPathToken()); |
||||
} |
||||
} |
||||
} |
||||
Object innerModel = parameters.get(0).getPath().evaluate(model, model, ctx.configuration()).getValue(); |
||||
if (ctx.configuration().jsonProvider().isArray(innerModel)) { |
||||
return ctx.configuration().jsonProvider().length(innerModel); |
||||
} |
||||
} |
||||
if (ctx.configuration().jsonProvider().isArray(model)) { |
||||
return ctx.configuration().jsonProvider().length(model); |
||||
} else if(ctx.configuration().jsonProvider().isMap(model)){ |
||||
return ctx.configuration().jsonProvider().length(model); |
||||
} |
||||
return null; |
||||
} |
||||
package com.jayway.jsonpath.internal.function.text; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.GsonBuilder; |
||||
import com.jayway.jsonpath.internal.EvaluationContext; |
||||
import com.jayway.jsonpath.internal.Path; |
||||
import com.jayway.jsonpath.internal.PathRef; |
||||
import com.jayway.jsonpath.internal.function.Parameter; |
||||
import com.jayway.jsonpath.internal.function.PathFunction; |
||||
import com.jayway.jsonpath.internal.path.CompiledPath; |
||||
import com.jayway.jsonpath.internal.path.PathToken; |
||||
import com.jayway.jsonpath.internal.path.RootPathToken; |
||||
import com.jayway.jsonpath.internal.path.WildcardPathToken; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Provides the length of a JSONArray Object |
||||
* |
||||
* Created by mattg on 6/26/15. |
||||
*/ |
||||
public class Length implements PathFunction { |
||||
|
||||
public static final String TOKEN_NAME = "length"; |
||||
|
||||
/** |
||||
* When we calculate the length of a path, what we're asking is given the node we land on how many children does it |
||||
* have. Thus when we wrote the original query what we really wanted was $..book.length() or $.length($..book.*) |
||||
* |
||||
* @param currentPath |
||||
* The current path location inclusive of the function name |
||||
* @param parent |
||||
* The path location above the current function |
||||
* |
||||
* @param model |
||||
* The JSON model as input to this particular function |
||||
* |
||||
* @param ctx |
||||
* Eval context, state bag used as the path is traversed, maintains the result of executing |
||||
* |
||||
* @param parameters |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) { |
||||
if (null != parameters && parameters.size() > 0) { |
||||
|
||||
// Set the tail of the first parameter, when its not a function path parameter (which wouldn't make sense
|
||||
// for length - to the wildcard such that we request all of its children so we can get back an array and
|
||||
// take its length.
|
||||
Parameter lengthOfParameter = parameters.get(0); |
||||
if (!lengthOfParameter.getPath().isFunctionPath()) { |
||||
Path path = lengthOfParameter.getPath(); |
||||
if (path instanceof CompiledPath) { |
||||
RootPathToken root = ((CompiledPath) path).getRoot(); |
||||
PathToken tail = root.getNext(); |
||||
while (null != tail && null != tail.getNext()) { |
||||
tail = tail.getNext(); |
||||
} |
||||
if (ctx.configuration().jsonProvider().isMap(model) && null != tail) { |
||||
tail.setNext(new WildcardPathToken()); |
||||
} |
||||
} |
||||
} |
||||
Object innerModel = parameters.get(0).getPath().evaluate(model, model, ctx.configuration()).getValue(); |
||||
if (ctx.configuration().jsonProvider().isArray(innerModel)) { |
||||
return ctx.configuration().jsonProvider().length(innerModel); |
||||
} |
||||
} |
||||
if (ctx.configuration().jsonProvider().isArray(model)) { |
||||
return ctx.configuration().jsonProvider().length(model); |
||||
} else if(ctx.configuration().jsonProvider().isMap(model)){ |
||||
return ctx.configuration().jsonProvider().length(model); |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -1,79 +1,154 @@
|
||||
package com.jayway.jsonpath; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.junit.Test; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import static com.jayway.jsonpath.JsonPath.using; |
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class JsonOrgJsonProviderTest extends BaseTest { |
||||
|
||||
|
||||
@Test |
||||
public void an_object_can_be_read() { |
||||
|
||||
JSONObject book = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[0]"); |
||||
|
||||
assertThat(book.get("author").toString()).isEqualTo("Nigel Rees"); |
||||
} |
||||
|
||||
@Test |
||||
public void a_property_can_be_read() { |
||||
|
||||
String category = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[0].category"); |
||||
|
||||
assertThat(category).isEqualTo("reference"); |
||||
} |
||||
|
||||
@Test |
||||
public void a_filter_can_be_applied() { |
||||
|
||||
JSONArray fictionBooks = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'fiction')]"); |
||||
|
||||
assertThat(fictionBooks.length()).isEqualTo(3); |
||||
} |
||||
|
||||
@Test |
||||
public void result_can_be_mapped_to_object() { |
||||
|
||||
List<Map<String, Object>> books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book", List.class); |
||||
|
||||
assertThat(books.size()).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void read_books_with_isbn() { |
||||
|
||||
JSONArray books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$..book[?(@.isbn)]"); |
||||
|
||||
assertThat(books.length()).isEqualTo(2); |
||||
} |
||||
|
||||
/** |
||||
* Functions take parameters, the length parameter for example takes an entire document which we anticipate |
||||
* will compute to a document that is an array of elements which can determine its length. |
||||
* |
||||
* Since we translate this query from $..books.length() to length($..books) verify that this particular translation |
||||
* works as anticipated. |
||||
*/ |
||||
@Test |
||||
public void read_book_length_using_translated_query() { |
||||
Integer result = using(Configuration.defaultConfiguration()) |
||||
.parse(JSON_BOOK_STORE_DOCUMENT) |
||||
.read("$..book.length()"); |
||||
assertThat(result).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void read_book_length() { |
||||
Object result = using(Configuration.defaultConfiguration()) |
||||
.parse(JSON_BOOK_STORE_DOCUMENT) |
||||
.read("$.length($..book)"); |
||||
assertThat(result).isEqualTo(4); |
||||
} |
||||
|
||||
} |
||||
package com.jayway.jsonpath; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.junit.Test; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import static com.jayway.jsonpath.JsonPath.using; |
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class JsonOrgJsonProviderTest extends BaseTest { |
||||
|
||||
|
||||
@Test |
||||
public void an_object_can_be_read() { |
||||
|
||||
JSONObject book = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[0]"); |
||||
|
||||
assertThat(book.get("author").toString()).isEqualTo("Nigel Rees"); |
||||
} |
||||
|
||||
@Test |
||||
public void a_property_can_be_read() { |
||||
|
||||
String category = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[0].category"); |
||||
|
||||
assertThat(category).isEqualTo("reference"); |
||||
} |
||||
|
||||
@Test |
||||
public void a_filter_can_be_applied() { |
||||
|
||||
JSONArray fictionBooks = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'fiction')]"); |
||||
|
||||
assertThat(fictionBooks.length()).isEqualTo(3); |
||||
} |
||||
|
||||
@Test |
||||
public void result_can_be_mapped_to_object() { |
||||
|
||||
List<Map<String, Object>> books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book", List.class); |
||||
|
||||
assertThat(books.size()).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void read_books_with_isbn() { |
||||
|
||||
JSONArray books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read("$..book[?(@.isbn)]"); |
||||
|
||||
assertThat(books.length()).isEqualTo(2); |
||||
} |
||||
|
||||
/** |
||||
* Functions take parameters, the length parameter for example takes an entire document which we anticipate |
||||
* will compute to a document that is an array of elements which can determine its length. |
||||
* |
||||
* Since we translate this query from $..books.length() to length($..books) verify that this particular translation |
||||
* works as anticipated. |
||||
*/ |
||||
@Test |
||||
public void read_book_length_using_translated_query() { |
||||
Integer result = using(Configuration.defaultConfiguration()) |
||||
.parse(JSON_BOOK_STORE_DOCUMENT) |
||||
.read("$..book.length()"); |
||||
assertThat(result).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void read_book_length_using_translated_query_with_filter() { |
||||
Object result = using(Configuration.defaultConfiguration()) |
||||
.parse(JSON_BOOK_STORE_DOCUMENT) |
||||
.read("$..[?(@.category == \"fiction\")].length()"); |
||||
assertThat(result).isEqualTo(3); |
||||
} |
||||
|
||||
@Test |
||||
public void read_book_length() { |
||||
Object result = using(Configuration.defaultConfiguration()) |
||||
.parse(JSON_BOOK_STORE_DOCUMENT) |
||||
.read("$.length($..book)"); |
||||
assertThat(result).isEqualTo(4); |
||||
} |
||||
|
||||
@Test |
||||
public void test(){ |
||||
String json = "[\n" + |
||||
" {\n" + |
||||
" \"author\": \"Nigel Rees\",\n" + |
||||
" \"category\": \"reference\",\n" + |
||||
" \"price\": 8.95,\n" + |
||||
" \"title\": \"Sayings of the Century\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"Evelyn Waugh\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"price\": 12.99,\n" + |
||||
" \"title\": \"Sword of Honour\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"Herman Melville\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"isbn\": \"0-553-21311-3\",\n" + |
||||
" \"price\": 8.99,\n" + |
||||
" \"title\": \"Moby Dick\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"J. R. R. Tolkien\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"isbn\": \"0-395-19395-8\",\n" + |
||||
" \"price\": 22.99,\n" + |
||||
" \"title\": \"The Lord of the Rings\"\n" + |
||||
" }\n" + |
||||
"]"; |
||||
Object result = JsonPath.read(json,"$..[?(@.price < 10)].length()"); |
||||
assertThat(result).isEqualTo(2); |
||||
} |
||||
|
||||
@Test |
||||
public void test2(){ |
||||
String json = "[\n" + |
||||
" {\n" + |
||||
" \"author\": \"Nigel Rees\",\n" + |
||||
" \"category\": \"reference\",\n" + |
||||
" \"price\": 8.95,\n" + |
||||
" \"title\": \"Sayings of the Century\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"Evelyn Waugh\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"price\": 12.99,\n" + |
||||
" \"title\": \"Sword of Honour\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"Herman Melville\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"isbn\": \"0-553-21311-3\",\n" + |
||||
" \"price\": 8.99,\n" + |
||||
" \"title\": \"Moby Dick\"\n" + |
||||
" },\n" + |
||||
" {\n" + |
||||
" \"author\": \"J. R. R. Tolkien\",\n" + |
||||
" \"category\": \"fiction\",\n" + |
||||
" \"isbn\": \"0-395-19395-8\",\n" + |
||||
" \"price\": 22.99,\n" + |
||||
" \"title\": \"The Lord of the Rings\"\n" + |
||||
" }\n" + |
||||
"]"; |
||||
Object result = JsonPath.read(json,"$..[?(@.price == 22.99)].length()"); |
||||
assertThat(result).isEqualTo(1); |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue