From 974a84553c676989af580f0d0b7e63995118aa6c Mon Sep 17 00:00:00 2001 From: Kalle Stenflo Date: Sun, 4 Mar 2012 22:48:14 +0100 Subject: [PATCH] Added write ops to JsonModel. --- .../jsonpath/IndefinitePathException.java | 15 + .../java/com/jayway/jsonpath/JsonModel.java | 262 +++++++++++++++--- .../java/com/jayway/jsonpath/JsonPath.java | 14 +- .../jayway/jsonpath/internal/PathToken.java | 4 + .../jsonpath/internal/PathTokenizer.java | 16 +- .../internal/filter/ArrayEvalFilter.java | 5 + .../internal/filter/ArrayIndexFilter.java | 16 ++ .../jsonpath/internal/filter/FieldFilter.java | 22 +- .../jsonpath/internal/filter/Filter.java | 2 +- .../internal/filter/HasFieldFilter.java | 5 + .../internal/filter/PassthroughFilter.java | 5 + .../jsonpath/internal/filter/ScanFilter.java | 5 + .../internal/filter/WildcardFilter.java | 5 + .../jayway/jsonpath/JsonModelMappingTest.java | 115 ++++++++ .../com/jayway/jsonpath/JsonModelOpsTest.java | 124 +++++++++ .../com/jayway/jsonpath/JsonModelTest.java | 61 ---- 16 files changed, 549 insertions(+), 127 deletions(-) create mode 100644 json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java create mode 100644 json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java create mode 100644 json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java diff --git a/json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java b/json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java new file mode 100644 index 00000000..a63220bd --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/IndefinitePathException.java @@ -0,0 +1,15 @@ +package com.jayway.jsonpath; + +/** + * Created by IntelliJ IDEA. + * User: kallestenflo + * Date: 3/4/12 + * Time: 7:15 PM + */ +public class IndefinitePathException extends RuntimeException { + + + public IndefinitePathException(String path) { + super("The path " + path + " is not definite"); + } +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java b/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java index 48da791f..4fb19233 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java @@ -14,6 +14,8 @@ */ package com.jayway.jsonpath; +import com.jayway.jsonpath.internal.PathToken; +import com.jayway.jsonpath.spi.JsonProvider; import com.jayway.jsonpath.spi.JsonProviderFactory; import org.apache.commons.io.IOUtils; import org.codehaus.jackson.map.ObjectMapper; @@ -22,10 +24,7 @@ import org.codehaus.jackson.map.type.CollectionType; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static java.util.Arrays.asList; import static org.apache.commons.lang.Validate.notEmpty; @@ -103,6 +102,15 @@ public class JsonModel { } } + // -------------------------------------------------------- + // + // Getters + // + // -------------------------------------------------------- + public Object getJsonObject() { + return this.jsonObject; + } + // -------------------------------------------------------- // // Model readers @@ -111,10 +119,7 @@ public class JsonModel { @SuppressWarnings({"unchecked"}) public T get(String jsonPath) { - notEmpty(jsonPath, "jsonPath can not be null or empty"); - - JsonPath path = JsonPath.compile(jsonPath); - return (T) get(path); + return (T) get(JsonPath.compile(jsonPath)); } @SuppressWarnings({"unchecked"}) @@ -124,6 +129,34 @@ public class JsonModel { return (T) jsonPath.read(jsonObject); } + // -------------------------------------------------------- + // + // Model writers + // + // -------------------------------------------------------- + public ArrayOps opsForArray(String jsonPath) { + return opsForArray(JsonPath.compile(jsonPath)); + } + + public ArrayOps opsForArray(JsonPath jsonPath) { + notNull(jsonPath, "jsonPath can not be null"); + + List opsTarget = getTargetObject(jsonPath, List.class); + + return new DefaultArrayOps(opsTarget); + } + + public ObjectOps opsForObject(String jsonPath) { + return opsForObject(JsonPath.compile(jsonPath)); + } + + public ObjectOps opsForObject(JsonPath jsonPath) { + notNull(jsonPath, "jsonPath can not be null"); + + Map opsTarget = getTargetObject(jsonPath, Map.class); + + return new DefaultObjectOps(opsTarget); + } // -------------------------------------------------------- // @@ -135,9 +168,7 @@ public class JsonModel { } public String toJson(String jsonPath) { - notEmpty(jsonPath, "jsonPath can not be null or empty"); - - return JsonProviderFactory.getInstance().toJson(get(jsonPath)); + return toJson(JsonPath.compile(jsonPath)); } public String toJson(JsonPath jsonPath) { @@ -153,21 +184,18 @@ public class JsonModel { // -------------------------------------------------------- public JsonModel getSubModel(String jsonPath) { - notEmpty(jsonPath, "jsonPath can not be null or empty"); - - JsonPath path = JsonPath.compile(jsonPath); - return getSubModel(path); + return getSubModel(JsonPath.compile(jsonPath)); } public JsonModel getSubModel(JsonPath jsonPath) { notNull(jsonPath, "jsonPath can not be null"); Object subModel = jsonPath.read(jsonObject); - - if(!(subModel instanceof Map) && !(subModel instanceof List)){ - throw new InvalidModelPathException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel!=null?subModel.getClass():"null")); + + if (!(subModel instanceof Map) && !(subModel instanceof List)) { + throw new InvalidModelPathException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null")); } - + return new JsonModel(subModel); } @@ -176,10 +204,8 @@ public class JsonModel { // Mapping model readers // // -------------------------------------------------------- - public MappingModelReader map(final String jsonPath) { - notEmpty(jsonPath, "jsonPath can not be null or empty"); - - return new DefaultMappingModelReader(JsonModel.this.get(jsonPath)); + public MappingModelReader map(String jsonPath) { + return map(JsonPath.compile(jsonPath)); } public MappingModelReader map(final JsonPath jsonPath) { @@ -217,27 +243,195 @@ public class JsonModel { return new JsonModel(jsonInputStream); } + // -------------------------------------------------------- + // + // Private helpers + // + // -------------------------------------------------------- + private static ObjectMapper getObjectMapper() { + if (JsonModel.objectMapper == null) { + synchronized (JsonModel.class) { + try { + Class.forName("org.codehaus.jackson.map.ObjectMapper"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("org.codehaus.jackson.map.ObjectMapper not found on classpath. This is an optional dependency needed for POJO conversions."); + } + JsonModel.objectMapper = new ObjectMapper(); + } + } + return JsonModel.objectMapper; + } + + private T getTargetObject(JsonPath jsonPath, Class clazz) { + notNull(jsonPath, "jsonPath can not be null"); + + if (!jsonPath.isPathDefinite()) { + throw new IndefinitePathException(jsonPath.getPath()); + } + + JsonProvider jsonProvider = JsonProviderFactory.getInstance(); + + Object modelRef = jsonObject; + + LinkedList tokens = jsonPath.getTokenizer().getPathTokens(); + + PathToken currentToken; + do { + currentToken = tokens.poll(); + modelRef = currentToken.get(modelRef, jsonProvider); + } while (!tokens.isEmpty()); + + if (modelRef.getClass().isAssignableFrom(clazz)) { + throw new InvalidModelPathException(jsonPath + " does nor refer to a Map but " + (currentToken != null ? currentToken.getClass().getName() : "null")); + } + return clazz.cast(modelRef); + } + // -------------------------------------------------------- // // Interfaces // // -------------------------------------------------------- - public interface MappingModelReader { + public interface MappingModelReader extends ListMappingModelReader, ObjectMappingModelReader { + + } + + public interface ObjectMappingModelReader { + T to(Class targetClass); + } + + public interface ListMappingModelReader { + List of(Class targetClass); ListMappingModelReader toList(); List toListOf(Class targetClass); Set toSetOf(Class targetClass); + } + + public interface ObjectOps { + + Map getTarget(); + + boolean containsKey(String key); + + ObjectOps put(String key, Object value); + + ObjectOps putAll(Map map); + + ObjectOps remove(String key); T to(Class targetClass); } - public interface ListMappingModelReader { - List of(Class targetClass); + public interface ArrayOps { + List getTarget(); + + ArrayOps add(Object o); + + ArrayOps addAll(Collection collection); + + ArrayOps remove(Object o); + + ListMappingModelReader toList(); + + List toListOf(Class targetClass); + + Set toSetOf(Class targetClass); + } + + private static class DefaultObjectOps implements ObjectOps { + + private Map opsTarget; + + private DefaultObjectOps(Map opsTarget) { + + this.opsTarget = opsTarget; + } + + @Override + public Map getTarget() { + return opsTarget; + } + + @Override + public boolean containsKey(String key) { + return opsTarget.containsKey(key); + } + + @Override + public ObjectOps put(String key, Object value) { + opsTarget.put(key, value); + return this; + } + + @Override + public ObjectOps putAll(Map map) { + opsTarget.putAll(map); + return this; + } + + @Override + public ObjectOps remove(String key) { + opsTarget.remove(key); + return this; + } + + @Override + public T to(Class targetClass) { + return new DefaultMappingModelReader(opsTarget).to(targetClass); + } + } + + private static class DefaultArrayOps implements ArrayOps { + + private List opsTarget; + + private DefaultArrayOps(List opsTarget) { + this.opsTarget = opsTarget; + } + + @Override + public List getTarget() { + return opsTarget; + } + + @Override + public ArrayOps add(Object o) { + opsTarget.add(o); + return this; + } + + @Override + public ArrayOps addAll(Collection collection) { + opsTarget.addAll(collection); + return this; + } + + @Override + public ArrayOps remove(Object o) { + opsTarget.remove(o); + return this; + } + + @Override + public ListMappingModelReader toList() { + return new DefaultMappingModelReader(opsTarget); + } + + @Override + public List toListOf(Class targetClass) { + return new DefaultMappingModelReader(opsTarget).toListOf(targetClass); + } + + @Override + public Set toSetOf(Class targetClass) { + return new DefaultMappingModelReader(opsTarget).toSetOf(targetClass); + } } - private static class DefaultMappingModelReader implements MappingModelReader, ListMappingModelReader { + private static class DefaultMappingModelReader implements MappingModelReader { private ObjectMapper objectMapper; private Object model; @@ -284,19 +478,5 @@ public class JsonModel { } - // -------------------------------------------------------- - // - // Private helpers - // - // -------------------------------------------------------- - private static ObjectMapper getObjectMapper() { - if (JsonModel.objectMapper == null) { - synchronized (JsonModel.class) { - JsonModel.objectMapper = new ObjectMapper(); - } - } - return JsonModel.objectMapper; - } - } diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java index 64baaad7..f77eb472 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java @@ -18,6 +18,7 @@ package com.jayway.jsonpath; import com.jayway.jsonpath.internal.PathToken; import com.jayway.jsonpath.internal.PathTokenizer; import com.jayway.jsonpath.internal.filter.Filter; +import com.jayway.jsonpath.spi.JsonProvider; import com.jayway.jsonpath.spi.JsonProviderFactory; import org.apache.commons.io.IOUtils; @@ -108,6 +109,15 @@ public class JsonPath { this.tokenizer = new PathTokenizer(jsonPath); } + PathTokenizer getTokenizer(){ + return this.tokenizer; + } + + /** + * Returns the string representation of this JsonPath + * + * @return path as String + */ public String getPath() { return this.tokenizer.getPath(); } @@ -154,13 +164,15 @@ public class JsonPath { throw new IllegalArgumentException("Invalid container object"); } + JsonProvider jsonProvider = JsonProviderFactory.getInstance(); + Object result = jsonObject; boolean inArrayContext = false; for (PathToken pathToken : tokenizer) { Filter filter = pathToken.getFilter(); - result = filter.filter(result, JsonProviderFactory.getInstance(), inArrayContext); + result = filter.filter(result, jsonProvider, inArrayContext); if (!inArrayContext) { inArrayContext = filter.isArrayFilter(); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java index 48edae04..47aac100 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java @@ -37,6 +37,10 @@ public class PathToken { return FilterFactory.createFilter(fragment).filter(model, jsonProvider); } + public Object get(Object model, JsonProvider jsonProvider){ + return FilterFactory.createFilter(fragment).getRef(model, jsonProvider); + } + public String getFragment() { return fragment; } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java b/json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java index efe0c7d1..afaa4330 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java @@ -16,6 +16,7 @@ package com.jayway.jsonpath.internal; import com.jayway.jsonpath.InvalidPathException; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -25,18 +26,17 @@ import java.util.List; */ public class PathTokenizer implements Iterable { - private String path; - private char[] pathChars; - private int index = 0; private List pathTokens = new LinkedList(); + private char[] pathChars; + private transient int index = 0; + public PathTokenizer(String jsonPath) { if (!jsonPath.startsWith("$") && !jsonPath.startsWith("$[")) { jsonPath = "$." + jsonPath; } - this.path = jsonPath; - this.pathChars = path.toCharArray(); + this.pathChars = jsonPath.toCharArray(); for (String pathFragment : splitPath()) { pathTokens.add(new PathToken(pathFragment)); @@ -52,7 +52,11 @@ public class PathTokenizer implements Iterable { } public String getPath() { - return path; + return new String(pathChars); + } + + public LinkedList getPathTokens(){ + return new LinkedList(pathTokens); } public Iterator iterator() { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java index 15c3297b..616a2fa3 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java @@ -59,6 +59,11 @@ public class ArrayEvalFilter extends Filter { return result; } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + throw new UnsupportedOperationException(""); + } + @Override public boolean isArrayFilter() { return true; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java index 49039c1b..f152eb50 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java @@ -17,11 +17,15 @@ package com.jayway.jsonpath.internal.filter; import com.jayway.jsonpath.spi.JsonProvider; import java.util.List; +import java.util.regex.Pattern; /** * @author Kalle Stenflo */ public class ArrayIndexFilter extends Filter { + + private static final Pattern SINGLE_ARRAY_INDEX_PATTERN = Pattern.compile("\\[\\d+\\]"); + public ArrayIndexFilter(String condition) { super(condition); } @@ -70,6 +74,18 @@ public class ArrayIndexFilter extends Filter { } } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + if(SINGLE_ARRAY_INDEX_PATTERN.matcher(condition).matches()){ + String trimmedCondition = trim(condition, 1, 1); + List src = jsonProvider.toList(obj); + return src.get(Integer.parseInt(trimmedCondition)); + + } else { + throw new UnsupportedOperationException(); + } + } + @Override public boolean isArrayFilter() { return true; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java index 623d44c0..4abc0d5f 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java @@ -59,28 +59,16 @@ public class FieldFilter extends Filter { public Object filter(Object obj, JsonProvider jsonProvider) { if (jsonProvider.isList(obj)) { return obj; - /* - List result = jsonProvider.createList(); - for (Object current : jsonProvider.toList(obj)) { - if (jsonProvider.isMap(current)) { - Map map = jsonProvider.toMap(current); - if (map.containsKey(condition)) { - Object o = map.get(condition); - if (jsonProvider.isList(o)) { - result.addAll(jsonProvider.toList(o)); - } else { - result.add(map.get(condition)); - } - } - } - } - return result; - */ } else { return jsonProvider.getMapValue(obj, condition); } } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + return filter(obj, jsonProvider); + } + @Override public boolean isArrayFilter() { return false; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/Filter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/Filter.java index 2b6d5f5e..715e27e9 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/Filter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/Filter.java @@ -46,7 +46,7 @@ public abstract class Filter { public abstract Object filter(Object obj, JsonProvider jsonProvider); - + public abstract Object getRef(Object obj, JsonProvider jsonProvider); public abstract boolean isArrayFilter(); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java index bccf223f..993e17f8 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java @@ -55,6 +55,11 @@ public class HasFieldFilter extends Filter { return result; } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + throw new UnsupportedOperationException(); + } + @Override public boolean isArrayFilter() { return true; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java index 1881081e..c40cbdf4 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java @@ -33,6 +33,11 @@ public class PassthroughFilter extends Filter { return obj; } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + return obj; + } + @Override public boolean isArrayFilter() { return isArrayFilter; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java index 37472be6..5b0688bc 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java @@ -41,6 +41,11 @@ public class ScanFilter extends Filter { return true; } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + throw new UnsupportedOperationException(); + } + private void scan(Object container, List result, JsonProvider jsonProvider) { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java index 3034ab9d..e4cd4e83 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java @@ -45,6 +45,11 @@ public class WildcardFilter extends Filter { return result; } + @Override + public Object getRef(Object obj, JsonProvider jsonProvider) { + throw new UnsupportedOperationException(); + } + @Override public boolean isArrayFilter() { return true; diff --git a/json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java b/json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java new file mode 100644 index 00000000..7db788c3 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/JsonModelMappingTest.java @@ -0,0 +1,115 @@ +package com.jayway.jsonpath; + +import org.junit.Test; + +import java.util.List; +import java.util.Set; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by IntelliJ IDEA. + * User: kallestenflo + * Date: 3/4/12 + * Time: 8:36 PM + */ +public class JsonModelMappingTest { + + public final static String DOCUMENT = + "{ \"store\": {\n" + + " \"book\": [ \n" + + " { \"category\": \"reference\",\n" + + " \"author\": \"Nigel Rees\",\n" + + " \"title\": \"Sayings of the Century\",\n" + + " \"price\": 8.95\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"Evelyn Waugh\",\n" + + " \"title\": \"Sword of Honour\",\n" + + " \"price\": 12.99\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"Herman Melville\",\n" + + " \"title\": \"Moby Dick\",\n" + + " \"isbn\": \"0-553-21311-3\",\n" + + " \"price\": 8.99\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"J. R. R. Tolkien\",\n" + + " \"title\": \"The Lord of the Rings\",\n" + + " \"isbn\": \"0-395-19395-8\",\n" + + " \"price\": 22.99\n" + + " }\n" + + " ],\n" + + " \"bicycle\": {\n" + + " \"color\": \"red\",\n" + + " \"price\": 19.95,\n" + + " \"foo:bar\": \"fooBar\",\n" + + " \"dot.notation\": \"new\"\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void map_a_json_model_to_an_Class() throws Exception { + + JsonModel model = JsonModel.create(DOCUMENT); + + Book book = model.map("$.store.book[1]").to(Book.class); + + assertEquals("fiction", book.category); + assertEquals("Evelyn Waugh", book.author); + assertEquals("Sword of Honour", book.title); + assertEquals(12.99D, book.price); + } + + @Test + public void map_a_json_model_to_a_List() throws Exception { + JsonModel model = JsonModel.create(DOCUMENT); + + List booksList = model.map("$.store.book[0,1]").toListOf(Book.class); + + assertEquals("fiction", booksList.get(1).category); + assertEquals("Evelyn Waugh", booksList.get(1).author); + assertEquals("Sword of Honour", booksList.get(1).title); + assertEquals(12.99D, booksList.get(1).price); + + booksList = model.map("$.store.book[*]").toListOf(Book.class); + + assertEquals("fiction", booksList.get(1).category); + assertEquals("Evelyn Waugh", booksList.get(1).author); + assertEquals("Sword of Honour", booksList.get(1).title); + assertEquals(12.99D, booksList.get(1).price); + + booksList = model.map("$.store.book[*]").toList().of(Book.class); + + assertEquals("fiction", booksList.get(1).category); + assertEquals("Evelyn Waugh", booksList.get(1).author); + assertEquals("Sword of Honour", booksList.get(1).title); + assertEquals(12.99D, booksList.get(1).price); + } + + @Test + public void map_a_json_model_to_a_Set() throws Exception { + + JsonModel model = JsonModel.create(DOCUMENT); + + Set bookSet = model.map("$.store.book[1]").toSetOf(Book.class); + + Book book = bookSet.iterator().next(); + + assertEquals("fiction", book.category); + assertEquals("Evelyn Waugh", book.author); + assertEquals("Sword of Honour", book.title); + assertEquals(12.99D, book.price); + } + + + public static class Book { + public String category; + public String author; + public String title; + public String isbn; + public Double price; + } +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java b/json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java new file mode 100644 index 00000000..e4638f80 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/JsonModelOpsTest.java @@ -0,0 +1,124 @@ +package com.jayway.jsonpath; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by IntelliJ IDEA. + * User: kallestenflo + * Date: 3/4/12 + * Time: 4:55 PM + */ +public class JsonModelOpsTest { + + public final static String DOCUMENT = + "{ \"store\": {\n" + + " \"book\": [ \n" + + " { \"category\": \"reference\",\n" + + " \"author\": \"Nigel Rees\",\n" + + " \"title\": \"Sayings of the Century\",\n" + + " \"price\": 8.95\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"Evelyn Waugh\",\n" + + " \"title\": \"Sword of Honour\",\n" + + " \"price\": 12.99\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"Herman Melville\",\n" + + " \"title\": \"Moby Dick\",\n" + + " \"isbn\": \"0-553-21311-3\",\n" + + " \"price\": 8.99\n" + + " },\n" + + " { \"category\": \"fiction\",\n" + + " \"author\": \"J. R. R. Tolkien\",\n" + + " \"title\": \"The Lord of the Rings\",\n" + + " \"isbn\": \"0-395-19395-8\",\n" + + " \"price\": 22.99\n" + + " }\n" + + " ],\n" + + " \"bicycle\": {\n" + + " \"color\": \"red\",\n" + + " \"price\": 19.95,\n" + + " \"foo:bar\": \"fooBar\",\n" + + " \"dot.notation\": \"new\"\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void object_ops_can_update() throws Exception { + + JsonModel model = JsonModel.create(DOCUMENT); + + model.opsForObject("store.book[0]") + .put("author", "Kalle") + .put("price", 12.30D); + + assertEquals("Kalle", model.get("store.book[0].author")); + assertEquals(12.30D, model.get("store.book[0].price")); + } + + + @Test + public void array_ops_can_add_element() throws Exception { + JsonModel model = JsonModel.create(DOCUMENT); + + Map newBook = new HashMap(); + newBook.put("category", "reference"); + newBook.put("author", "Kalle"); + newBook.put("title", "JSONPath book"); + newBook.put("isbn", "0-553-21311-34"); + newBook.put("price", 12.10D); + + model.opsForArray("store.book").add(newBook); + + JsonModel subModel = model.getSubModel("store.book[4]"); + + assertEquals("reference", subModel.get("category")); + assertEquals("Kalle", subModel.get("author")); + assertEquals("JSONPath book", subModel.get("title")); + assertEquals("0-553-21311-34", subModel.get("isbn")); + assertEquals(12.10D, subModel.get("price")); + } + + @Test + public void arrays_can_be_mapped() throws Exception { + JsonModel model = JsonModel.create(DOCUMENT); + + List books1 = model.opsForArray("store.book").toList().of(Book.class); + List books2 = model.opsForArray("store.book").toListOf(Book.class); + Set books3 = model.opsForArray("store.book").toSetOf(Book.class); + + assertEquals(4, books1.size()); + assertEquals(4, books2.size()); + assertEquals(4, books3.size()); + } + + @Test + public void objects_can_be_mapped() throws Exception { + JsonModel model = JsonModel.create(DOCUMENT); + + Book book = model.opsForObject("store.book[1]").to(Book.class); + + assertEquals("fiction", book.category); + assertEquals("Evelyn Waugh", book.author); + assertEquals("Sword of Honour", book.title); + assertEquals(12.99D, book.price); + + } + + public static class Book { + public String category; + public String author; + public String title; + public String isbn; + public Double price; + } +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java b/json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java index 4b547b7d..29f38c7e 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java @@ -84,68 +84,7 @@ public class JsonModelTest { assertEquals("{\"child\":{\"key\":\"value\"},\"items\":[0,1,2]}", model.toJson()); } - @Test - public void map_a_json_model_to_an_Class() throws Exception { - - JsonModel model = JsonModel.create(DOCUMENT); - - Book book = model.map("$.store.book[1]").to(Book.class); - - assertEquals("fiction", book.category); - assertEquals("Evelyn Waugh", book.author); - assertEquals("Sword of Honour", book.title); - assertEquals(12.99D, book.price); - } - - @Test - public void map_a_json_model_to_a_List() throws Exception { - JsonModel model = JsonModel.create(DOCUMENT); - - List booksList = model.map("$.store.book[0,1]").toListOf(Book.class); - - assertEquals("fiction", booksList.get(1).category); - assertEquals("Evelyn Waugh", booksList.get(1).author); - assertEquals("Sword of Honour", booksList.get(1).title); - assertEquals(12.99D, booksList.get(1).price); - - booksList = model.map("$.store.book[*]").toListOf(Book.class); - - assertEquals("fiction", booksList.get(1).category); - assertEquals("Evelyn Waugh", booksList.get(1).author); - assertEquals("Sword of Honour", booksList.get(1).title); - assertEquals(12.99D, booksList.get(1).price); - booksList = model.map("$.store.book[*]").toList().of(Book.class); - - assertEquals("fiction", booksList.get(1).category); - assertEquals("Evelyn Waugh", booksList.get(1).author); - assertEquals("Sword of Honour", booksList.get(1).title); - assertEquals(12.99D, booksList.get(1).price); - } - - @Test - public void map_a_json_model_to_a_Set() throws Exception { - - JsonModel model = JsonModel.create(DOCUMENT); - - Set bookSet = model.map("$.store.book[1]").toSetOf(Book.class); - - Book book = bookSet.iterator().next(); - - assertEquals("fiction", book.category); - assertEquals("Evelyn Waugh", book.author); - assertEquals("Sword of Honour", book.title); - assertEquals(12.99D, book.price); - } - - - public static class Book { - public String category; - public String author; - public String title; - public String isbn; - public Double price; - } }