|
|
@ -14,8 +14,9 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
package com.jayway.jsonpath; |
|
|
|
package com.jayway.jsonpath; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.jayway.jsonpath.internal.ConvertUtils; |
|
|
|
import com.jayway.jsonpath.internal.PathToken; |
|
|
|
import com.jayway.jsonpath.internal.PathToken; |
|
|
|
import com.jayway.jsonpath.internal.Util; |
|
|
|
import com.jayway.jsonpath.internal.IOUtils; |
|
|
|
import com.jayway.jsonpath.spi.JsonProvider; |
|
|
|
import com.jayway.jsonpath.spi.JsonProvider; |
|
|
|
import com.jayway.jsonpath.spi.JsonProviderFactory; |
|
|
|
import com.jayway.jsonpath.spi.JsonProviderFactory; |
|
|
|
import com.jayway.jsonpath.spi.MappingProviderFactory; |
|
|
|
import com.jayway.jsonpath.spi.MappingProviderFactory; |
|
|
@ -26,17 +27,18 @@ import java.net.URL; |
|
|
|
import java.util.*; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
|
|
|
|
import static java.util.Arrays.asList; |
|
|
|
import static java.util.Arrays.asList; |
|
|
|
import static org.apache.commons.lang.Validate.notEmpty; |
|
|
|
import static org.apache.commons.lang.Validate.*; |
|
|
|
import static org.apache.commons.lang.Validate.notNull; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* A JsonModel represents a parsed JSON document that provides easy and efficient read operations. In contrast to the |
|
|
|
* A JsonModel holds a parsed JSON document and provides easy read and write operations. In contrast to the |
|
|
|
* static read operations provided by {@link JsonPath} a JsonModel will only parse the document once. |
|
|
|
* static read operations provided by {@link JsonPath} a JsonModel will only parse the document once. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Kalle Stenflo |
|
|
|
* @author Kalle Stenflo |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class JsonModel { |
|
|
|
public class JsonModel { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final JsonPath JSON_PATH_ROOT = JsonPath.compile("$"); |
|
|
|
private Object jsonObject; |
|
|
|
private Object jsonObject; |
|
|
|
private JsonProvider jsonProvider; |
|
|
|
private JsonProvider jsonProvider; |
|
|
|
|
|
|
|
|
|
|
@ -98,23 +100,71 @@ public class JsonModel { |
|
|
|
this.jsonObject = jsonProvider.parse(jsonInputStream); |
|
|
|
this.jsonObject = jsonProvider.parse(jsonInputStream); |
|
|
|
this.jsonProvider = jsonProvider; |
|
|
|
this.jsonProvider = jsonProvider; |
|
|
|
} finally { |
|
|
|
} finally { |
|
|
|
Util.closeQuietly(jsonInputStream); |
|
|
|
IOUtils.closeQuietly(jsonInputStream); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Check if this JsonModel is holding a JSON array as to object |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return true if root is an array |
|
|
|
|
|
|
|
*/ |
|
|
|
public boolean isList() { |
|
|
|
public boolean isList() { |
|
|
|
return jsonProvider.isList(jsonObject); |
|
|
|
return jsonProvider.isList(jsonObject); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Check if this JsonModel is holding a JSON object as to object |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return true if root is an object |
|
|
|
|
|
|
|
*/ |
|
|
|
public boolean isMap() { |
|
|
|
public boolean isMap() { |
|
|
|
return jsonProvider.isMap(jsonObject); |
|
|
|
return jsonProvider.isMap(jsonObject); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Check if this JsonModel has the given definite path |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see com.jayway.jsonpath.JsonPath#isPathDefinite() |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath path to check |
|
|
|
|
|
|
|
* @return true if model contains path |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public boolean hasPath(String jsonPath){ |
|
|
|
|
|
|
|
return hasPath(JsonPath.compile(jsonPath)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Check if this JsonModel has the given definite path |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see com.jayway.jsonpath.JsonPath#isPathDefinite() |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath path to check |
|
|
|
|
|
|
|
* @return true if model contains path |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public boolean hasPath(JsonPath jsonPath){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isTrue(jsonPath.isPathDefinite(), "hasPath can only be used for definite paths"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
get(jsonPath); |
|
|
|
|
|
|
|
} catch(InvalidPathException e){ |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Getters
|
|
|
|
// Getters
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the root object of this JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return returns the root object |
|
|
|
|
|
|
|
*/ |
|
|
|
public Object getJsonObject() { |
|
|
|
public Object getJsonObject() { |
|
|
|
return this.jsonObject; |
|
|
|
return this.jsonObject; |
|
|
|
} |
|
|
|
} |
|
|
@ -125,11 +175,51 @@ public class JsonModel { |
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads the given path from this JsonModel. Filters is a way to problematically filter the contents of a list. |
|
|
|
|
|
|
|
* Instead of writing the filter criteria directly inside the JsonPath expression the filter is indicated and |
|
|
|
|
|
|
|
* provided as an argument. |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* All three statements below are equivalent |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* <code> |
|
|
|
|
|
|
|
* JsonModel model = JsonModel.model(myJson); |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* //A
|
|
|
|
|
|
|
|
* List<String> books = model.read("$store.book[?(@author == 'Nigel Rees')]"); |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* //B
|
|
|
|
|
|
|
|
* List<String> books = model.read("$store.book[?]", filter(where("author").is("Nigel Rees")); |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* //C
|
|
|
|
|
|
|
|
* JsonPath path = JsonPath.compile("$store.book[?]", filter(where("author").is("Nigel Rees")); |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* List<String> books = model.read(path); |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* </code> |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* The filters are applied in the order they are provided. If a path contains multiple [?] filter markers |
|
|
|
|
|
|
|
* the filters must be passed in the correct order. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the path to read |
|
|
|
|
|
|
|
* @param filters filters to use in the path |
|
|
|
|
|
|
|
* @param <T> expected return type |
|
|
|
|
|
|
|
* @return the json path result |
|
|
|
|
|
|
|
* @see Filter |
|
|
|
|
|
|
|
* @see Criteria |
|
|
|
|
|
|
|
*/ |
|
|
|
@SuppressWarnings({"unchecked"}) |
|
|
|
@SuppressWarnings({"unchecked"}) |
|
|
|
public <T> T get(String jsonPath, Filter... filters) { |
|
|
|
public <T> T get(String jsonPath, Filter... filters) { |
|
|
|
return (T) get(JsonPath.compile(jsonPath, filters)); |
|
|
|
return (T) get(JsonPath.compile(jsonPath, filters)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads the given path from this JsonModel. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the path to read |
|
|
|
|
|
|
|
* @param <T> expected return type |
|
|
|
|
|
|
|
* @return the json path result |
|
|
|
|
|
|
|
*/ |
|
|
|
@SuppressWarnings({"unchecked"}) |
|
|
|
@SuppressWarnings({"unchecked"}) |
|
|
|
public <T> T get(JsonPath jsonPath) { |
|
|
|
public <T> T get(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
@ -142,36 +232,80 @@ public class JsonModel { |
|
|
|
// Model writers
|
|
|
|
// Model writers
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
public ArrayOps opsForArray(String jsonPath) { |
|
|
|
|
|
|
|
return opsForArray(JsonPath.compile(jsonPath)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ArrayOps} for this JsonModel. Note that the root element of this model |
|
|
|
|
|
|
|
* must be a json array. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return array operations for this JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public ArrayOps opsForArray() { |
|
|
|
public ArrayOps opsForArray() { |
|
|
|
return new DefaultArrayOps(this.jsonObject); |
|
|
|
isTrue(jsonProvider.isList(jsonObject), "This JsonModel is not a JSON array"); |
|
|
|
|
|
|
|
return opsForArray(JSON_PATH_ROOT); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ArrayOps} for the array inside this JsonModel identified by the given JsonPath. The path must |
|
|
|
|
|
|
|
* be definite ({@link com.jayway.jsonpath.JsonPath#isPathDefinite()}). |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* Note that the element returned by the given path must be a json array. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath definite path to array to perform operations on |
|
|
|
|
|
|
|
* @return array operations for the targeted array |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public ArrayOps opsForArray(String jsonPath) { |
|
|
|
|
|
|
|
return opsForArray(JsonPath.compile(jsonPath)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ArrayOps} for the array inside this JsonModel identified by the given JsonPath. The path must |
|
|
|
|
|
|
|
* be definite ({@link com.jayway.jsonpath.JsonPath#isPathDefinite()}). |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* Note that the element returned by the given path must be a json array. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath definite path to array to perform operations on |
|
|
|
|
|
|
|
* @return array operations for the targeted array |
|
|
|
|
|
|
|
*/ |
|
|
|
public ArrayOps opsForArray(JsonPath jsonPath) { |
|
|
|
public ArrayOps opsForArray(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
return new DefaultArrayOps(jsonPath); |
|
|
|
Object opsTarget = getTargetObject(jsonPath, List.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new DefaultArrayOps(opsTarget); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ObjectOps} for this JsonModel. Note that the root element of this model |
|
|
|
|
|
|
|
* must be a json object. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return object operations for this JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public ObjectOps opsForObject() { |
|
|
|
public ObjectOps opsForObject() { |
|
|
|
return new DefaultObjectOps(this.jsonObject); |
|
|
|
return opsForObject(JSON_PATH_ROOT); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ObjectOps} for the object inside this JsonModel identified by the given JsonPath. The path must |
|
|
|
|
|
|
|
* be definite ({@link com.jayway.jsonpath.JsonPath#isPathDefinite()}). |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* Note that the element returned by the given path must be a json object. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath definite path to object to perform operations on |
|
|
|
|
|
|
|
* @return object operations for the targeted object |
|
|
|
|
|
|
|
*/ |
|
|
|
public ObjectOps opsForObject(String jsonPath) { |
|
|
|
public ObjectOps opsForObject(String jsonPath) { |
|
|
|
return opsForObject(JsonPath.compile(jsonPath)); |
|
|
|
return opsForObject(JsonPath.compile(jsonPath)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets an {@link ObjectOps} for the object inside this JsonModel identified by the given JsonPath. The path must |
|
|
|
|
|
|
|
* be definite ({@link com.jayway.jsonpath.JsonPath#isPathDefinite()}). |
|
|
|
|
|
|
|
* <p/> |
|
|
|
|
|
|
|
* Note that the element returned by the given path must be a json object. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath definite path to object to perform operations on |
|
|
|
|
|
|
|
* @return object operations for the targeted object |
|
|
|
|
|
|
|
*/ |
|
|
|
public ObjectOps opsForObject(JsonPath jsonPath) { |
|
|
|
public ObjectOps opsForObject(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
return new DefaultObjectOps(jsonPath); |
|
|
|
Object opsTarget = getTargetObject(jsonPath, Map.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new DefaultObjectOps(opsTarget); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
@ -179,15 +313,31 @@ public class JsonModel { |
|
|
|
// JSON extractors
|
|
|
|
// JSON extractors
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
public String getJson() { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JSON representation of this JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return model as Json |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public String toJson() { |
|
|
|
return jsonProvider.toJson(jsonObject); |
|
|
|
return jsonProvider.toJson(jsonObject); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String getJson(String jsonPath, Filter... filters) { |
|
|
|
/** |
|
|
|
return getJson(JsonPath.compile(jsonPath, filters)); |
|
|
|
* Creates a JSON representation of the result of the provided JsonPath |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return path result as Json |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public String toJson(String jsonPath, Filter... filters) { |
|
|
|
|
|
|
|
return toJson(JsonPath.compile(jsonPath, filters)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String getJson(JsonPath jsonPath) { |
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JSON representation of the result of the provided JsonPath |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return path result as Json |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public String toJson(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
|
|
|
|
return jsonProvider.toJson(get(jsonPath)); |
|
|
|
return jsonProvider.toJson(get(jsonPath)); |
|
|
@ -199,19 +349,83 @@ public class JsonModel { |
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public JsonModel getModel(String jsonPath, Filter... filters) { |
|
|
|
/** |
|
|
|
return getModel(JsonPath.compile(jsonPath, filters)); |
|
|
|
* Returns a sub model from this JsonModel. A sub model can be any JSON object or JSON array |
|
|
|
|
|
|
|
* addressed by a definite path. In contrast to a detached model changes on the sub model |
|
|
|
|
|
|
|
* will be applied on the source model (the JsonModel from which the sub model was created) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the absolute path to extract a JsonModel for |
|
|
|
|
|
|
|
* @return the new JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see com.jayway.jsonpath.JsonPath#isPathDefinite() |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public JsonModel getSubModel(String jsonPath) { |
|
|
|
|
|
|
|
return getSubModel(JsonPath.compile(jsonPath)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public JsonModel getModel(JsonPath jsonPath) { |
|
|
|
/** |
|
|
|
|
|
|
|
* Returns a sub model from this JsonModel. A sub model can be any JSON object or JSON array |
|
|
|
|
|
|
|
* addressed by a definite path. In contrast to a detached model changes on the sub model |
|
|
|
|
|
|
|
* will be applied on the source model (the JsonModel from which the sub model was created) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the absolute path to extract a JsonModel for |
|
|
|
|
|
|
|
* @return the new JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see com.jayway.jsonpath.JsonPath#isPathDefinite() |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public JsonModel getSubModel(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isTrue(jsonPath.isPathDefinite(), "You can only get subModels with a definite path. Use getDetachedModel if path is not definite."); |
|
|
|
|
|
|
|
|
|
|
|
Object subModel = jsonPath.read(jsonObject); |
|
|
|
Object subModel = jsonPath.read(jsonObject); |
|
|
|
|
|
|
|
|
|
|
|
if (!jsonProvider.isContainer(subModel)) { |
|
|
|
if (!jsonProvider.isContainer(subModel)) { |
|
|
|
throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null")); |
|
|
|
throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new JsonSubModel(subModel, this.jsonProvider, this, jsonPath); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Detached sub model readers
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a detached sub model from this JsonModel. A detached sub model does not have |
|
|
|
|
|
|
|
* to be created using a definite path. Changes on a detached sub model will not be reflected on the |
|
|
|
|
|
|
|
* source model (the JsonModel from which the sub model was created). |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the absolute path to extract a JsonModel for |
|
|
|
|
|
|
|
* @param filters filters to expand the path |
|
|
|
|
|
|
|
* @return a detached JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public JsonModel getSubModelDetached(String jsonPath, Filter... filters) { |
|
|
|
|
|
|
|
return getSubModelDetached(JsonPath.compile(jsonPath, filters)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a detached sub model from this JsonModel. A detached sub model does not have |
|
|
|
|
|
|
|
* to be created using a definite path. Changes on a detached sub model will not be reflected on the |
|
|
|
|
|
|
|
* source model (the JsonModel from which the sub model was created). |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonPath the absolute path to extract a JsonModel for |
|
|
|
|
|
|
|
* @return a detached JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public JsonModel getSubModelDetached(JsonPath jsonPath) { |
|
|
|
|
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object subModel = jsonPath.read(jsonObject); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!jsonProvider.isContainer(subModel)) { |
|
|
|
|
|
|
|
throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subModel = jsonProvider.clone(subModel); |
|
|
|
|
|
|
|
|
|
|
|
return new JsonModel(subModel, this.jsonProvider); |
|
|
|
return new JsonModel(subModel, this.jsonProvider); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -220,14 +434,33 @@ public class JsonModel { |
|
|
|
// Mapping model readers
|
|
|
|
// Mapping model readers
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns a {@link MappingModelReader} for this JsonModel. Note that to use this functionality you need |
|
|
|
|
|
|
|
* an optional dependencies on your classpath (jackson-mapper-asl ver >= 1.9.5) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return a object mapper |
|
|
|
|
|
|
|
*/ |
|
|
|
public MappingModelReader map() { |
|
|
|
public MappingModelReader map() { |
|
|
|
return new DefaultMappingModelReader(this.jsonObject); |
|
|
|
return new DefaultMappingModelReader(this.jsonObject); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns a {@link MappingModelReader} for the JsonModel targeted by the provided {@link JsonPath}. Note that to use this functionality you need |
|
|
|
|
|
|
|
* an optional dependencies on your classpath (jackson-mapper-asl ver >= 1.9.5) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return a object mapper |
|
|
|
|
|
|
|
*/ |
|
|
|
public MappingModelReader map(String jsonPath, Filter... filters) { |
|
|
|
public MappingModelReader map(String jsonPath, Filter... filters) { |
|
|
|
return map(JsonPath.compile(jsonPath, filters)); |
|
|
|
return map(JsonPath.compile(jsonPath, filters)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns a {@link MappingModelReader} for the JsonModel targeted by the provided {@link JsonPath}. Note that to use this functionality you need |
|
|
|
|
|
|
|
* an optional dependencies on your classpath (jackson-mapper-asl ver >= 1.9.5) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return a object mapper |
|
|
|
|
|
|
|
*/ |
|
|
|
public MappingModelReader map(JsonPath jsonPath) { |
|
|
|
public MappingModelReader map(JsonPath jsonPath) { |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
notNull(jsonPath, "jsonPath can not be null"); |
|
|
|
|
|
|
|
|
|
|
@ -239,24 +472,49 @@ public class JsonModel { |
|
|
|
// Static factory methods
|
|
|
|
// Static factory methods
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param json json string |
|
|
|
|
|
|
|
* @return a new JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public static JsonModel model(String json) { |
|
|
|
public static JsonModel model(String json) { |
|
|
|
notEmpty(json, "json can not be null or empty"); |
|
|
|
notEmpty(json, "json can not be null or empty"); |
|
|
|
|
|
|
|
|
|
|
|
return new JsonModel(json, JsonProviderFactory.createProvider()); |
|
|
|
return new JsonModel(json, JsonProviderFactory.createProvider()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonObject a json container (a {@link Map} or a {@link List}) |
|
|
|
|
|
|
|
* @return a new JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public static JsonModel model(Object jsonObject) { |
|
|
|
public static JsonModel model(Object jsonObject) { |
|
|
|
notNull(jsonObject, "jsonObject can not be null"); |
|
|
|
notNull(jsonObject, "jsonObject can not be null"); |
|
|
|
|
|
|
|
|
|
|
|
return new JsonModel(jsonObject, JsonProviderFactory.createProvider()); |
|
|
|
return new JsonModel(jsonObject, JsonProviderFactory.createProvider()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param url pointing to a Json document |
|
|
|
|
|
|
|
* @return a new JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public static JsonModel model(URL url) throws IOException { |
|
|
|
public static JsonModel model(URL url) throws IOException { |
|
|
|
notNull(url, "url can not be null"); |
|
|
|
notNull(url, "url can not be null"); |
|
|
|
|
|
|
|
|
|
|
|
return new JsonModel(url, JsonProviderFactory.createProvider()); |
|
|
|
return new JsonModel(url, JsonProviderFactory.createProvider()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates a JsonModel |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param jsonInputStream json document stream |
|
|
|
|
|
|
|
* @return a new JsonModel |
|
|
|
|
|
|
|
*/ |
|
|
|
public static JsonModel model(InputStream jsonInputStream) throws IOException { |
|
|
|
public static JsonModel model(InputStream jsonInputStream) throws IOException { |
|
|
|
notNull(jsonInputStream, "jsonInputStream can not be null"); |
|
|
|
notNull(jsonInputStream, "jsonInputStream can not be null"); |
|
|
|
|
|
|
|
|
|
|
@ -280,6 +538,13 @@ public class JsonModel { |
|
|
|
|
|
|
|
|
|
|
|
Object modelRef = jsonObject; |
|
|
|
Object modelRef = jsonObject; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jsonPath.getTokenizer().size() == 1) { |
|
|
|
|
|
|
|
PathToken onlyToken = jsonPath.getTokenizer().iterator().next(); |
|
|
|
|
|
|
|
if ("$".equals(onlyToken.getFragment())) { |
|
|
|
|
|
|
|
return clazz.cast(modelRef); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
LinkedList<PathToken> tokens = jsonPath.getTokenizer().getPathTokens(); |
|
|
|
LinkedList<PathToken> tokens = jsonPath.getTokenizer().getPathTokens(); |
|
|
|
|
|
|
|
|
|
|
|
PathToken currentToken; |
|
|
|
PathToken currentToken; |
|
|
@ -293,6 +558,31 @@ public class JsonModel { |
|
|
|
} |
|
|
|
} |
|
|
|
return clazz.cast(modelRef); |
|
|
|
return clazz.cast(modelRef); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
throw new InvalidModelException(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setTargetObject(JsonPath jsonPath, Object newValue) { |
|
|
|
|
|
|
|
JsonPath setterPath = jsonPath.copy(); |
|
|
|
|
|
|
|
PathToken pathToken = setterPath.getTokenizer().removeLastPathToken(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pathToken.isRootToken()) { |
|
|
|
|
|
|
|
if (this instanceof JsonSubModel) { |
|
|
|
|
|
|
|
JsonSubModel thisModel = (JsonSubModel) this; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
thisModel.parent.setTargetObject(thisModel.subModelPath, newValue); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.jsonObject = newValue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (pathToken.isArrayIndexToken()) { |
|
|
|
|
|
|
|
int arrayIndex = pathToken.getArrayIndex(); |
|
|
|
|
|
|
|
opsForArray(setterPath).set(arrayIndex, newValue); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
opsForObject(setterPath).put(pathToken.getFragment(), newValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
@ -300,178 +590,353 @@ public class JsonModel { |
|
|
|
//
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts a {@link JsonModel} to an Object |
|
|
|
|
|
|
|
*/ |
|
|
|
public interface ObjectMappingModelReader { |
|
|
|
public interface ObjectMappingModelReader { |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts this JsonModel to the specified class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see MappingProviderFactory |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param targetClass class to convert the {@link JsonModel} to |
|
|
|
|
|
|
|
* @param <T> template class
|
|
|
|
|
|
|
|
* @return the mapped model |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> T to(Class<T> targetClass); |
|
|
|
<T> T to(Class<T> targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts a {@link JsonModel} to an {@link Collection} of Objects |
|
|
|
|
|
|
|
*/ |
|
|
|
public interface ListMappingModelReader { |
|
|
|
public interface ListMappingModelReader { |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts this JsonModel to the a list of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param targetClass class to convert the {@link JsonModel} array items to |
|
|
|
|
|
|
|
* @param <T> template class
|
|
|
|
|
|
|
|
* @return the mapped mode |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> List<T> of(Class<T> targetClass); |
|
|
|
<T> List<T> of(Class<T> targetClass); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Syntactic sugar function to use with {@link ListMappingModelReader#of} |
|
|
|
|
|
|
|
*/ |
|
|
|
ListMappingModelReader toList(); |
|
|
|
ListMappingModelReader toList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts this JsonModel to the a {@link List} of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param targetClass class to convert the {@link JsonModel} array items to |
|
|
|
|
|
|
|
* @param <T> template class
|
|
|
|
|
|
|
|
* @return the mapped mode |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> List<T> toListOf(Class<T> targetClass); |
|
|
|
<T> List<T> toListOf(Class<T> targetClass); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts this JsonModel to the a {@link Set} of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param targetClass class to convert the {@link JsonModel} array items to |
|
|
|
|
|
|
|
* @param <T> template class
|
|
|
|
|
|
|
|
* @return the mapped model |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> Set<T> toSetOf(Class<T> targetClass); |
|
|
|
<T> Set<T> toSetOf(Class<T> targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Object mapping interface used when for root object that can be either a {@link List} or a {@link Map}. |
|
|
|
|
|
|
|
* It's up to the invoker to know what the conversion target can be mapped to. |
|
|
|
|
|
|
|
*/ |
|
|
|
public interface MappingModelReader extends ListMappingModelReader, ObjectMappingModelReader { |
|
|
|
public interface MappingModelReader extends ListMappingModelReader, ObjectMappingModelReader { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Operations that can be performed on Json objects ({@link Map}s) |
|
|
|
|
|
|
|
*/ |
|
|
|
public interface ObjectOps { |
|
|
|
public interface ObjectOps { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the operation target |
|
|
|
|
|
|
|
* @return the operation target |
|
|
|
|
|
|
|
*/ |
|
|
|
Map<String, Object> getTarget(); |
|
|
|
Map<String, Object> getTarget(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see Map#containsKey(Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
boolean containsKey(String key); |
|
|
|
boolean containsKey(String key); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see Map#put(Object, Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
ObjectOps put(String key, Object value); |
|
|
|
ObjectOps put(String key, Object value); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Adds the value to the target map if it is not already present |
|
|
|
|
|
|
|
* @param key the key |
|
|
|
|
|
|
|
* @param value the value |
|
|
|
|
|
|
|
* @return this {@link ObjectOps} |
|
|
|
|
|
|
|
*/ |
|
|
|
ObjectOps putIfAbsent(String key, Object value); |
|
|
|
ObjectOps putIfAbsent(String key, Object value); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see Map#get(Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
Object get(String key); |
|
|
|
Object get(String key); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Tries to convert the value associated with the key to an {@link Integer} |
|
|
|
|
|
|
|
* @param key the key |
|
|
|
|
|
|
|
* @return converted value |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Integer getInteger(String key); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Tries to convert the value associated with the key to an {@link Long} |
|
|
|
|
|
|
|
* @param key the key |
|
|
|
|
|
|
|
* @return converted value |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Long getLong(String key); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Tries to convert the value associated with the key to an {@link Double} |
|
|
|
|
|
|
|
* @param key the key |
|
|
|
|
|
|
|
* @return converted value |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Double getDouble(String key); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see Map#putAll(java.util.Map) |
|
|
|
|
|
|
|
*/ |
|
|
|
ObjectOps putAll(Map<String, Object> map); |
|
|
|
ObjectOps putAll(Map<String, Object> map); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see Map#remove(Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
ObjectOps remove(String key); |
|
|
|
ObjectOps remove(String key); |
|
|
|
|
|
|
|
|
|
|
|
ObjectOps transform(Transformer<JsonModel> transformer); |
|
|
|
/** |
|
|
|
|
|
|
|
* Allows transformations of the target object. the target for this {@link ObjectOps} will be be replaced |
|
|
|
|
|
|
|
* with the {@link Object} returned by the {@link Transformer#transform(Object)} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param transformer the transformer to use |
|
|
|
|
|
|
|
* @return this {@link ObjectOps} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
ObjectOps transform(Transformer<Map<String, Object>> transformer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Map the target of this {@link ObjectOps} to the provided class
|
|
|
|
|
|
|
|
* @param targetClass class to convert the target object to |
|
|
|
|
|
|
|
* @param <T> template class
|
|
|
|
|
|
|
|
* @return the mapped model |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> T to(Class<T> targetClass); |
|
|
|
<T> T to(Class<T> targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Operations that can be performed on Json arrays ({@link List}s) |
|
|
|
|
|
|
|
*/ |
|
|
|
public interface ArrayOps { |
|
|
|
public interface ArrayOps { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the operation target |
|
|
|
|
|
|
|
* @return the operation target |
|
|
|
|
|
|
|
*/ |
|
|
|
List<Object> getTarget(); |
|
|
|
List<Object> getTarget(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see List#add(Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
ArrayOps add(Object o); |
|
|
|
ArrayOps add(Object o); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see List#addAll(java.util.Collection) |
|
|
|
|
|
|
|
*/ |
|
|
|
ArrayOps addAll(Collection<Object> collection); |
|
|
|
ArrayOps addAll(Collection<Object> collection); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see List#remove(int) |
|
|
|
|
|
|
|
*/ |
|
|
|
ArrayOps remove(Object o); |
|
|
|
ArrayOps remove(Object o); |
|
|
|
|
|
|
|
|
|
|
|
ListMappingModelReader toList(); |
|
|
|
/** |
|
|
|
|
|
|
|
* @see java.util.List#size() |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
int size(); |
|
|
|
|
|
|
|
|
|
|
|
ArrayOps transform(Transformer<Object> transformer); |
|
|
|
/** |
|
|
|
|
|
|
|
* @see List#set(int, Object) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
ArrayOps set(int index, Object value); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Allows transformations of the target list. The target for this {@link ArrayOps} will be be replaced |
|
|
|
|
|
|
|
* with the {@link Object} returned by the {@link Transformer#transform(Object)} |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param transformer the transformer to use |
|
|
|
|
|
|
|
* @return this {@link ArrayOps} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
ArrayOps transform(Transformer<List<Object>> transformer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see ListMappingModelReader |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
ListMappingModelReader toList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see ListMappingModelReader |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> List<T> toListOf(Class<T> targetClass); |
|
|
|
<T> List<T> toListOf(Class<T> targetClass); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see ListMappingModelReader |
|
|
|
|
|
|
|
*/ |
|
|
|
<T> Set<T> toSetOf(Class<T> targetClass); |
|
|
|
<T> Set<T> toSetOf(Class<T> targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static class DefaultObjectOps implements ObjectOps { |
|
|
|
private class DefaultObjectOps implements ObjectOps { |
|
|
|
|
|
|
|
|
|
|
|
private Map<String, Object> opsTarget; |
|
|
|
private JsonPath jsonPath; |
|
|
|
|
|
|
|
|
|
|
|
private DefaultObjectOps(Object opsTarget) { |
|
|
|
private DefaultObjectOps(JsonPath jsonPath) { |
|
|
|
this.opsTarget = (Map<String, Object>) opsTarget; |
|
|
|
this.jsonPath = jsonPath; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Map<String, Object> getTarget() { |
|
|
|
public Map<String, Object> getTarget() { |
|
|
|
return opsTarget; |
|
|
|
return getTargetObject(jsonPath, Map.class); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean containsKey(String key) { |
|
|
|
public boolean containsKey(String key) { |
|
|
|
return opsTarget.containsKey(key); |
|
|
|
return getTargetObject(jsonPath, Map.class).containsKey(key); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ObjectOps put(String key, Object value) { |
|
|
|
public ObjectOps put(String key, Object value) { |
|
|
|
opsTarget.put(key, value); |
|
|
|
getTargetObject(jsonPath, Map.class).put(key, value); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ObjectOps putIfAbsent(String key, Object value) { |
|
|
|
public ObjectOps putIfAbsent(String key, Object value) { |
|
|
|
if (!opsTarget.containsKey(key)) { |
|
|
|
Map targetObject = getTargetObject(jsonPath, Map.class); |
|
|
|
opsTarget.put(key, value); |
|
|
|
if (!targetObject.containsKey(key)) { |
|
|
|
|
|
|
|
targetObject.put(key, value); |
|
|
|
} |
|
|
|
} |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Object get(String key) { |
|
|
|
public Object get(String key) { |
|
|
|
return opsTarget.get(key); |
|
|
|
return getTargetObject(jsonPath, Map.class).get(key); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Integer getInteger(String key) { |
|
|
|
|
|
|
|
return ConvertUtils.toInt(get(key)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Long getLong(String key) { |
|
|
|
|
|
|
|
return ConvertUtils.toLong(get(key)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Double getDouble(String key) { |
|
|
|
|
|
|
|
return ConvertUtils.toDouble(get(key)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ObjectOps putAll(Map<String, Object> map) { |
|
|
|
public ObjectOps putAll(Map<String, Object> map) { |
|
|
|
opsTarget.putAll(map); |
|
|
|
getTargetObject(jsonPath, Map.class).putAll(map); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ObjectOps remove(String key) { |
|
|
|
public ObjectOps remove(String key) { |
|
|
|
opsTarget.remove(key); |
|
|
|
getTargetObject(jsonPath, Map.class).remove(key); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ObjectOps transform(Transformer<JsonModel> transformer) { |
|
|
|
public ObjectOps transform(Transformer<Map<String, Object>> transformer) { |
|
|
|
transformer.transform(-1, JsonModel.model(opsTarget)); |
|
|
|
Map targetObject = getTargetObject(jsonPath, Map.class); |
|
|
|
|
|
|
|
Object transformed = transformer.transform(targetObject); |
|
|
|
|
|
|
|
setTargetObject(jsonPath, transformed); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> T to(Class<T> targetClass) { |
|
|
|
public <T> T to(Class<T> targetClass) { |
|
|
|
return new DefaultMappingModelReader(opsTarget).to(targetClass); |
|
|
|
Map targetObject = getTargetObject(jsonPath, Map.class); |
|
|
|
|
|
|
|
return new DefaultMappingModelReader(targetObject).to(targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static class DefaultArrayOps implements ArrayOps { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<Object> opsTarget; |
|
|
|
private class DefaultArrayOps implements ArrayOps { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private JsonPath jsonPath; |
|
|
|
|
|
|
|
|
|
|
|
private DefaultArrayOps(Object opsTarget) { |
|
|
|
private DefaultArrayOps(JsonPath jsonPath) { |
|
|
|
this.opsTarget = (List<Object>) opsTarget; |
|
|
|
this.jsonPath = jsonPath; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public List<Object> getTarget() { |
|
|
|
public List<Object> getTarget() { |
|
|
|
return opsTarget; |
|
|
|
return getTargetObject(jsonPath, List.class); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ArrayOps add(Object o) { |
|
|
|
public ArrayOps add(Object o) { |
|
|
|
opsTarget.add(o); |
|
|
|
getTargetObject(jsonPath, List.class).add(o); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ArrayOps addAll(Collection<Object> collection) { |
|
|
|
public ArrayOps addAll(Collection<Object> collection) { |
|
|
|
opsTarget.addAll(collection); |
|
|
|
getTargetObject(jsonPath, List.class).addAll(collection); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ArrayOps remove(Object o) { |
|
|
|
public ArrayOps remove(Object o) { |
|
|
|
opsTarget.remove(o); |
|
|
|
getTargetObject(jsonPath, List.class).remove(o); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ListMappingModelReader toList() { |
|
|
|
public int size() { |
|
|
|
return new DefaultMappingModelReader(opsTarget); |
|
|
|
return getTargetObject(jsonPath, List.class).size(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public ArrayOps set(int index, Object value) { |
|
|
|
|
|
|
|
getTargetObject(jsonPath, List.class).set(index, value); |
|
|
|
|
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ArrayOps transform(Transformer<Object> transformer) { |
|
|
|
public ListMappingModelReader toList() { |
|
|
|
for (int i = 0; i < opsTarget.size(); i++) { |
|
|
|
return new DefaultMappingModelReader(getTargetObject(jsonPath, List.class)); |
|
|
|
Object current = opsTarget.get(i); |
|
|
|
|
|
|
|
opsTarget.set(i, transformer.transform(i, current)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public ArrayOps transform(Transformer<List<Object>> transformer) { |
|
|
|
|
|
|
|
Object transformed = transformer.transform(getTargetObject(jsonPath, List.class)); |
|
|
|
|
|
|
|
setTargetObject(jsonPath, transformed); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> List<T> toListOf(Class<T> targetClass) { |
|
|
|
public <T> List<T> toListOf(Class<T> targetClass) { |
|
|
|
return new DefaultMappingModelReader(opsTarget).toListOf(targetClass); |
|
|
|
return new DefaultMappingModelReader(getTargetObject(jsonPath, List.class)).toListOf(targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> Set<T> toSetOf(Class<T> targetClass) { |
|
|
|
public <T> Set<T> toSetOf(Class<T> targetClass) { |
|
|
|
return new DefaultMappingModelReader(opsTarget).toSetOf(targetClass); |
|
|
|
return new DefaultMappingModelReader(getTargetObject(jsonPath, List.class)).toSetOf(targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -517,4 +982,16 @@ public class JsonModel { |
|
|
|
return MappingProviderFactory.createProvider().convertValue(model, targetClass); |
|
|
|
return MappingProviderFactory.createProvider().convertValue(model, targetClass); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class JsonSubModel extends JsonModel { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final JsonModel parent; |
|
|
|
|
|
|
|
private final JsonPath subModelPath; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private JsonSubModel(Object jsonObject, JsonProvider jsonProvider, JsonModel parent, JsonPath subModelPath) { |
|
|
|
|
|
|
|
super(jsonObject, jsonProvider); |
|
|
|
|
|
|
|
this.parent = parent; |
|
|
|
|
|
|
|
this.subModelPath = subModelPath; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|