diff --git a/build.gradle b/build.gradle index 8c9c7ee8..0a2d2ae7 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ ext { jacksonDatabind: 'com.fasterxml.jackson.core:jackson-databind:2.6.3', gson: 'com.google.code.gson:gson:2.3.1', jsonOrg: 'org.json:json:20140107', + tapestryJson: 'org.apache.tapestry:tapestry-json:5.4-rc-1', hamcrestCore: 'org.hamcrest:hamcrest-core:1.3', hamcrestLibrary: 'org.hamcrest:hamcrest-library:1.3', diff --git a/json-path/build.gradle b/json-path/build.gradle index 13407efc..fd7c690d 100644 --- a/json-path/build.gradle +++ b/json-path/build.gradle @@ -19,6 +19,7 @@ dependencies { compile libs.jacksonDatabind, optional compile libs.gson, optional compile libs.jsonOrg, optional + compile libs.tapestryJson, optional testCompile libs.test } @@ -51,6 +52,10 @@ task distZip(type: Zip, dependsOn: assemble) { into 'lib-optional/jsonOrg' include { it.file.name.contains('json-2') } } + from(project.configurations.compile) { + into 'lib-optional/jsonOrg' + include { it.file.name.contains('tapestry') } + } } task distTar(type: Tar, dependsOn: assemble) { @@ -83,6 +88,10 @@ task distTar(type: Tar, dependsOn: assemble) { into 'lib-optional/jsonOrg' include { it.file.name.contains('json-2') } } + from(project.configurations.compile) { + into 'lib-optional/jsonOrg' + include { it.file.name.contains('tapestry') } + } } task dist(){ diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/json/TapestryJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/spi/json/TapestryJsonProvider.java new file mode 100644 index 00000000..55563c88 --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/json/TapestryJsonProvider.java @@ -0,0 +1,105 @@ +package com.jayway.jsonpath.spi.json; + +import java.io.InputStream; +import java.util.Collection; +import java.util.Scanner; + +import org.apache.tapestry5.json.JSONArray; +import org.apache.tapestry5.json.JSONCollection; +import org.apache.tapestry5.json.JSONObject; + +import com.jayway.jsonpath.InvalidJsonException; + +public class TapestryJsonProvider extends AbstractJsonProvider { + + public static final TapestryJsonProvider INSTANCE = new TapestryJsonProvider(); + + @Override + public Object parse(final String json) throws InvalidJsonException { + return new JSONObject(json); + } + + @Override + public Object parse(final InputStream jsonStream, final String charset) throws InvalidJsonException { + Scanner sc = null; + try { + sc = new Scanner(jsonStream, charset); + return parse(sc.useDelimiter("\\A").next()); + } finally { + if (sc != null) { + sc.close(); + } + } + } + + @Override + public String toJson(final Object obj) { + return ((JSONCollection) obj).toCompactString(); + } + + @Override + public Object createArray() { + return new JSONArray(); + } + + @Override + public Object createMap() { + return new JSONObject(); + } + + @Override + public void setProperty(final Object obj, final Object key, final Object value) { + Object v = value == null ? JSONObject.NULL : value; + if (isMap(obj)) { + ((JSONObject) obj).put(key.toString(), v); + } + } + + @Override + public boolean isMap(final Object obj) { + return obj instanceof JSONObject; + } + + @Override + public Object getArrayIndex(final Object obj, final int idx) { + return ((JSONArray) obj).get(idx); + } + + @Override + public Collection getPropertyKeys(final Object obj) { + return ((JSONObject) obj).keys(); + } + + @Override + public Object getMapValue(final Object obj, final String key) { + JSONObject json = (JSONObject) obj; + if (!json.has(key)) { + return UNDEFINED; + } + return json.get(key); + } + + @Override + public int length(final Object obj) { + if (obj instanceof JSONArray) { + return ((JSONArray) obj).length(); + } else if (obj instanceof JSONObject) { + return ((JSONObject) obj).length(); + } else { + throw new IllegalArgumentException("Cannot determine length of " + obj + ", unsupported type."); + } + } + + @Override + public boolean isArray(final Object obj) { + return (obj instanceof JSONArray); + } + + @Override + public void setArrayIndex(final Object array, final int index, final Object newValue) { + Object v = newValue == null ? JSONObject.NULL : newValue; + JSONArray list = (JSONArray) array; + list.put(index, v); + } + +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/mapper/TapestryMappingProvider.java b/json-path/src/main/java/com/jayway/jsonpath/spi/mapper/TapestryMappingProvider.java new file mode 100644 index 00000000..7c284cfb --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/mapper/TapestryMappingProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jayway.jsonpath.spi.mapper; + +import java.util.ArrayList; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.TypeRef; + +public class TapestryMappingProvider implements MappingProvider { + + @Override + public T map(final Object source, final Class targetType, final Configuration configuration) { + if (source == null) { + return null; + } + if (targetType.isAssignableFrom(source.getClass())) { + return (T) source; + } + try { + if (targetType.isAssignableFrom(ArrayList.class) && configuration.jsonProvider().isArray(source)) { + int length = configuration.jsonProvider().length(source); + @SuppressWarnings("rawtypes") + ArrayList list = new ArrayList(length); + for (Object o : configuration.jsonProvider().toIterable(source)) { + list.add(o); + } + return (T) list; + } + } catch (Exception e) { + + } + throw new MappingException("Cannot convert a " + source.getClass().getName() + " to a " + targetType + + " use Tapestry's TypeCoercer instead."); + } + + @Override + public T map(final Object source, final TypeRef targetType, final Configuration configuration) { + throw new UnsupportedOperationException( + "Tapestry JSON provider does not support TypeRef! Use a Jackson or Gson based provider"); + } + +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java b/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java index 7aec601b..d962822d 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java @@ -7,10 +7,12 @@ import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider; import com.jayway.jsonpath.spi.json.JacksonJsonProvider; import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider; import com.jayway.jsonpath.spi.json.JsonSmartJsonProvider; +import com.jayway.jsonpath.spi.json.TapestryJsonProvider; import com.jayway.jsonpath.spi.mapper.GsonMappingProvider; import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; import com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider; import com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider; +import com.jayway.jsonpath.spi.mapper.TapestryMappingProvider; import java.util.HashMap; @@ -45,6 +47,12 @@ public class BaseTest { .mappingProvider(new JsonSmartMappingProvider()) .jsonProvider(new JsonSmartJsonProvider()) .build(); + + public static final Configuration TAPESTRY_JSON_CONFIGURATION = Configuration + .builder() + .mappingProvider(new TapestryMappingProvider()) + .jsonProvider(TapestryJsonProvider.INSTANCE) + .build(); public static final String JSON_BOOK_DOCUMENT = "{ " + diff --git a/json-path/src/test/java/com/jayway/jsonpath/TapestryJsonProviderTest.java b/json-path/src/test/java/com/jayway/jsonpath/TapestryJsonProviderTest.java new file mode 100644 index 00000000..d2471436 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/TapestryJsonProviderTest.java @@ -0,0 +1,49 @@ +package com.jayway.jsonpath; + +import static com.jayway.jsonpath.JsonPath.using; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; + +import org.apache.tapestry5.json.JSONArray; +import org.apache.tapestry5.json.JSONObject; +import org.junit.Test; + +public class TapestryJsonProviderTest extends BaseTest { + + @Test + public void an_object_can_be_read() { + + JSONObject book = using(TAPESTRY_JSON_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(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[0].category"); + + assertThat(category).isEqualTo("reference"); + } + + @Test + public void a_filter_can_be_applied() { + + JSONArray fictionBooks = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT) + .read("$.store.book[?(@.category == 'fiction')]"); + + assertThat(fictionBooks.length()).isEqualTo(3); + } + + @Test + public void result_can_be_mapped_to_object() { + + List> books = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book", + List.class); + + assertThat(books.size()).isEqualTo(4); + } + +}