Browse Source

Added Converter to support type conversion.

pull/46/head
Kalle Stenflo 10 years ago
parent
commit
ecde41a1e1
  1. 2
      json-path-web-test/pom.xml
  2. 23
      json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
  3. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
  4. 7
      json-path/src/main/java/com/jayway/jsonpath/spi/converter/Converter.java
  5. 174
      json-path/src/main/java/com/jayway/jsonpath/spi/converter/ConverterFactory.java
  6. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java
  7. 6
      json-path/src/test/java/com/jayway/jsonpath/BaseTest.java
  8. 45
      json-path/src/test/java/com/jayway/jsonpath/ConverterTest.java
  9. 16
      json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java
  10. 25
      json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java

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

@ -59,7 +59,7 @@
<dependency> <dependency>
<groupId>com.jayway.jsonpath</groupId> <groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId> <artifactId>json-path</artifactId>
<version>0.9.2-SNAPSHOT</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>

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

@ -33,6 +33,17 @@ public interface ReadContext {
*/ */
<T> T read(String path, Predicate... filters); <T> T read(String path, Predicate... filters);
/**
* Reads the given path from this context
*
* @param path path to read
* @param type expected return type (will try to convert)
* @param filters filters
* @param <T>
* @return result
*/
<T> T read(String path, Class<T> type, Predicate... filters);
/** /**
* Reads the given path from this context * Reads the given path from this context
* *
@ -42,4 +53,16 @@ public interface ReadContext {
*/ */
<T> T read(JsonPath path); <T> T read(JsonPath path);
/**
* Reads the given path from this context
*
* @param path path to apply
* @param type expected return type (will try to convert)
* @param <T>
* @return result
*/
<T> T read(JsonPath path, Class<T> type);
} }

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

@ -5,6 +5,7 @@ import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ParseContext; import com.jayway.jsonpath.ParseContext;
import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.ReadContext; import com.jayway.jsonpath.ReadContext;
import com.jayway.jsonpath.spi.converter.ConverterFactory;
import com.jayway.jsonpath.spi.http.HttpProviderFactory; import com.jayway.jsonpath.spi.http.HttpProviderFactory;
import java.io.File; import java.io.File;
@ -92,10 +93,24 @@ public class JsonReader implements ParseContext, ReadContext {
return read(JsonPath.compile(path, filters)); return read(JsonPath.compile(path, filters));
} }
@Override
public <T> T read(String path, Class<T> type, Predicate... filters) {
return convert(read(path, filters), type);
}
@Override @Override
public <T> T read(JsonPath path) { public <T> T read(JsonPath path) {
notNull(path, "path can not be null"); notNull(path, "path can not be null");
return path.read(json, configuration); return path.read(json, configuration);
} }
@Override
public <T> T read(JsonPath path, Class<T> type) {
return convert(read(path), type);
}
private <T> T convert(Object obj, Class<T> type){
return ConverterFactory.createConverter(type).convert(obj, configuration);
}
} }

7
json-path/src/main/java/com/jayway/jsonpath/spi/converter/Converter.java

@ -0,0 +1,7 @@
package com.jayway.jsonpath.spi.converter;
import com.jayway.jsonpath.Configuration;
public interface Converter<T>{
T convert(Object o, Configuration conf);
}

174
json-path/src/main/java/com/jayway/jsonpath/spi/converter/ConverterFactory.java

@ -0,0 +1,174 @@
package com.jayway.jsonpath.spi.converter;
import com.jayway.jsonpath.Configuration;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ConverterFactory {
private static Map<Class<?>, Converter<?>> converters = new ConcurrentHashMap<Class<?>, Converter<?>>();
static {
registerConverter(Long.class, new LongConverter());
registerConverter(Integer.class, new IntegerConverter());
registerConverter(BigDecimal.class, new BigDecimalConverter());
registerConverter(Double.class, new DoubleConverter());
registerConverter(Date.class, new DateConverter());
registerConverter(String.class, new StringConverter());
}
public static <T> Converter<T> createConverter(Class<T> target){
Converter<T> converter = (Converter<T>) converters.get(target);
if(converter == null){
converter = new Converter<T>() {
@Override
public T convert(Object o, Configuration conf) {
return (T)o;
}
};
}
return converter;
}
public static <T> void registerConverter(Class<T> target, Converter<T> converter){
converters.put(target, converter);
}
public static <T> void unRegisterConverter(Class<T> target){
converters.remove(target);
}
private static class StringConverter implements Converter<String> {
@Override
public String convert(Object o, Configuration conf) {
if(o == null){
return null;
} else {
return o.toString();
}
}
}
private static class DateConverter implements Converter<Date> {
@Override
public Date convert(Object o, Configuration conf) {
if(o == null){
return null;
} else if(o instanceof Date){
return (Date)o;
} else if(o instanceof Long){
return new Date(((Long)o).longValue());
} else if(o instanceof String){
try {
return DateFormat.getInstance().parse(o.toString());
} catch (ParseException e) {
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + Integer.class.getName(), e);
}
}
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + Integer.class.getName());
}
}
private static class IntegerConverter implements Converter<Integer> {
@Override
public Integer convert(Object o, Configuration conf) {
if(o == null){
return null;
} else if(o instanceof Integer){
return (Integer)o;
} else if(o instanceof Long){
return ((Long)o).intValue();
} else if(o instanceof Double){
return ((Double)o).intValue();
} else if(o instanceof BigDecimal){
return ((BigDecimal)o).intValue();
} else if(o instanceof Float){
return ((Float)o).intValue();
} else if(o instanceof String){
return Integer.parseInt(o.toString());
}
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + Integer.class.getName());
}
}
private static class LongConverter implements Converter<Long> {
@Override
public Long convert(Object o, Configuration conf) {
if(o == null){
return null;
} else if(o instanceof Long){
return (Long)o;
} else if(o instanceof Integer){
return ((Integer)o).longValue();
} else if(o instanceof Double){
return ((Double)o).longValue();
} else if(o instanceof BigDecimal){
return ((BigDecimal)o).longValue();
} else if(o instanceof Float){
return ((Float)o).longValue();
} else if(o instanceof String){
return Long.parseLong(o.toString());
}
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + Long.class.getName());
}
}
private static class DoubleConverter implements Converter<Double> {
@Override
public Double convert(Object o, Configuration conf) {
if(o == null){
return null;
} else if(o instanceof Double){
return (Double)o;
} else if(o instanceof Integer){
return Double.valueOf(o.toString());
} else if(o instanceof Long){
return Double.valueOf(o.toString());
} else if(o instanceof BigDecimal){
return ((BigDecimal)o).doubleValue();
} else if(o instanceof Float){
return ((Float)o).doubleValue();
} else if(o instanceof String){
return Double.parseDouble(o.toString());
}
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + Double.class.getName());
}
}
private static class BigDecimalConverter implements Converter<BigDecimal> {
@Override
public BigDecimal convert(Object o, Configuration conf) {
if(o == null){
return null;
} else if(o instanceof BigDecimal){
return (BigDecimal)o;
} else if(o instanceof Integer){
return new BigDecimal(o.toString());
} else if(o instanceof Long){
return new BigDecimal(o.toString());
} else if(o instanceof Float){
return BigDecimal.valueOf(((Float)o).doubleValue());
} else if(o instanceof String){
return new BigDecimal(o.toString());
}
throw new IllegalArgumentException("Can not convert: " + o.getClass().getName() + " to: " + BigDecimal.class.getName());
}
}
}

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

@ -32,14 +32,12 @@ public interface JsonProvider {
Object parse(InputStream jsonStream) throws InvalidJsonException; Object parse(InputStream jsonStream) throws InvalidJsonException;
String toJson(Object obj); String toJson(Object obj);
Object createMap(); Object createMap();
Object createArray(); Object createArray();
Object clone(Object model); Object clone(Object model);
/** /**

6
json-path/src/test/java/com/jayway/jsonpath/BaseTest.java

@ -4,10 +4,12 @@ public class BaseTest {
public static final String JSON_DOCUMENT = "{\n" + public static final String JSON_DOCUMENT = "{\n" +
" \"string-property\" : \"string-value\", \n" + " \"string-property\" : \"string-value\", \n" +
" \"int-property\" : " + Integer.MAX_VALUE + ", \n" + " \"int-max-property\" : " + Integer.MAX_VALUE + ", \n" +
" \"long-property\" : " + Long.MAX_VALUE + ", \n" + " \"long-max-property\" : " + Long.MAX_VALUE + ", \n" +
" \"long-max-property\" : " + Long.MAX_VALUE + ", \n" +
" \"boolean-property\" : true, \n" + " \"boolean-property\" : true, \n" +
" \"null-property\" : null, \n" + " \"null-property\" : null, \n" +
" \"int-small-property\" : 1, \n" +
" \"store\" : {\n" + " \"store\" : {\n" +
" \"book\" : [\n" + " \"book\" : [\n" +
" {\n" + " {\n" +

45
json-path/src/test/java/com/jayway/jsonpath/ConverterTest.java

@ -0,0 +1,45 @@
package com.jayway.jsonpath;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.Date;
import static com.jayway.jsonpath.JsonPath.parse;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
public class ConverterTest extends BaseTest {
@Test
public void an_Integer_can_be_converted_to_a_Long() {
assertThat(parse(singletonMap("val", 1)).read("val", Long.class)).isEqualTo(1L);
}
@Test
public void an_String_can_be_converted_to_a_Long() {
assertThat(parse(singletonMap("val", "1")).read("val", Long.class)).isEqualTo(1L);
}
@Test
public void an_Integer_can_be_converted_to_a_String() {
assertThat(parse(singletonMap("val", 1)).read("val", String.class)).isEqualTo("1");
}
@Test
public void an_Integer_can_be_converted_to_a_Double() {
assertThat(parse(singletonMap("val", 1)).read("val", Double.class)).isEqualTo(1D);
}
@Test
public void a_BigDecimal_can_be_converted_to_a_Long() {
assertThat(parse(singletonMap("val", new BigDecimal(1.5D))).read("val", Long.class)).isEqualTo(1L);
}
@Test
public void a_Long_can_be_converted_to_a_Date() {
Date now = new Date();
assertThat(parse(singletonMap("val", now.getTime())).read("val", Date.class)).isEqualTo(now);
}
}

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

@ -0,0 +1,16 @@
package com.jayway.jsonpath;
import org.junit.Test;
public class OptionsTest extends BaseTest {
@Test
public void leafs_can_be_defaulted_to_null() {
//assertThat(parse(singletonMap("foo", "bar"))).
}
}

25
json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java

@ -3,52 +3,53 @@ package com.jayway.jsonpath;
import org.junit.Test; import org.junit.Test;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public class ReturnTypeTest extends BaseTest { public class ReturnTypeTest extends BaseTest {
private static ReadContext reader = JsonPath.parse(JSON_DOCUMENT);
@Test @Test
public void assert_strings_can_be_read() { public void assert_strings_can_be_read() {
assertThat(JsonPath.read(JSON_DOCUMENT, "$.string-property")).isEqualTo("string-value"); assertThat(reader.read("$.string-property")).isEqualTo("string-value");
} }
@Test @Test
public void assert_ints_can_be_read() { public void assert_ints_can_be_read() {
assertThat(JsonPath.read(JSON_DOCUMENT, "$.int-property")).isEqualTo(Integer.MAX_VALUE); assertThat(reader.read("$.int-max-property")).isEqualTo(Integer.MAX_VALUE);
} }
@Test @Test
public void assert_longs_can_be_read() { public void assert_longs_can_be_read() {
assertThat(JsonPath.read(JSON_DOCUMENT, "$.long-property")).isEqualTo(Long.MAX_VALUE); assertThat(reader.read("$.long-max-property")).isEqualTo(Long.MAX_VALUE);
} }
@Test @Test
public void assert_boolean_values_can_be_read() { public void assert_boolean_values_can_be_read() {
assertThat(JsonPath.read(JSON_DOCUMENT, "$.boolean-property")).isEqualTo(true); assertThat(reader.read("$.boolean-property")).isEqualTo(true);
} }
@Test @Test
public void assert_null_values_can_be_read() { public void assert_null_values_can_be_read() {
assertThat(JsonPath.read(JSON_DOCUMENT, "$.null-property")).isNull(); assertThat(reader.read("$.null-property")).isNull();
} }
@Test @Test
public void assert_arrays_can_be_read_2() { public void assert_arrays_can_be_read() {
List<Object> list = JsonPath.read(JSON_DOCUMENT, "$.store.book"); assertThat(reader.read("$.store.book", List.class)).hasSize(4);
assertThat(list).hasSize(4);
} }
@Test @Test
public void assert_maps_can_be_read() { public void assert_maps_can_be_read() {
/*
assertThat(JsonPath.parse(JSON_DOCUMENT).read("$.store.book[0]", Map.class) assertThat(reader.read("$.store.book[0]", Map.class))
.containsEntry("category", "reference") .containsEntry("category", "reference")
.containsEntry("author", "Nigel Rees") .containsEntry("author", "Nigel Rees")
.containsEntry("title", "Sayings of the Century") .containsEntry("title", "Sayings of the Century")
.containsEntry("display-price", 8.95D); .containsEntry("display-price", 8.95D);
*/
} }
} }

Loading…
Cancel
Save