Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.minidev.json.JSONNavi Maven / Gradle / Ivy
Go to download
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.
package net.minidev.json;
/*
* Copyright 2011-2023 JSON-SMART 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.
*/
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import net.minidev.json.writer.JsonReaderI;
/**
* A JQuery like Json editor, accessor.
*
* @since 1.0.9
*
* @author Uriel Chemouni <[email protected] >
*/
public class JSONNavi {
private JsonReaderI super T> mapper;
private T root;
private Stack stack = new Stack();
private Stack path = new Stack();
private Object current;
private boolean failure = false;
private String failureMessage;
private boolean readonly = false;
private Object missingKey = null;
public static JSONNavi newInstance() {
return new JSONNavi(JSONValue.defaultReader.DEFAULT_ORDERED);
}
public static JSONNavi newInstanceObject() {
JSONNavi o = new JSONNavi(JSONValue.defaultReader.getMapper(JSONObject.class));
o.object();
return o;
}
public static JSONNavi newInstanceArray() {
JSONNavi o = new JSONNavi(JSONValue.defaultReader.getMapper(JSONArray.class));
o.array();
return o;
}
public JSONNavi(JsonReaderI super T> mapper) {
this.mapper = mapper;
}
@SuppressWarnings("unchecked")
public JSONNavi(String json) {
this.root = (T) JSONValue.parse(json);
this.current = this.root;
readonly = true;
}
public JSONNavi(String json, JsonReaderI mapper) {
this.root = JSONValue.parse(json, mapper);
this.mapper = mapper;
this.current = this.root;
readonly = true;
}
public JSONNavi(String json, Class mapTo) {
this.root = JSONValue.parse(json, mapTo);
this.mapper = JSONValue.defaultReader.getMapper(mapTo);
this.current = this.root;
readonly = true;
}
/**
* return to root node
*
* @return the root node
*/
public JSONNavi root() {
this.current = this.root;
this.stack.clear();
this.path.clear();
this.failure = false;
this.missingKey = null;
this.failureMessage = null;
return this;
}
public boolean hasFailure() {
return failure;
}
public Object getCurrentObject() {
return current;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Collection getKeys() {
if (current instanceof Map)
return ((Map) current).keySet();
return null;
}
public int getSize() {
if (current == null)
return 0;
if (isArray())
return ((List>) current).size();
if (isObject())
return ((Map, ?>) current).size();
return 1;
}
public String getString(String key) {
String v = null;
if (!hasKey(key))
return v;
at(key);
v = asString();
up();
return v;
}
public int getInt(String key) {
int v = 0;
if (!hasKey(key))
return v;
at(key);
v = asInt();
up();
return v;
}
public Integer getInteger(String key) {
Integer v = null;
if (!hasKey(key))
return v;
at(key);
v = asIntegerObj();
up();
return v;
}
public double getDouble(String key) {
double v = 0;
if (!hasKey(key))
return v;
at(key);
v = asDouble();
up();
return v;
}
public boolean hasKey(String key) {
if (!isObject())
return false;
return o(current).containsKey(key);
}
public JSONNavi> at(String key) {
if (failure)
return this;
if (!isObject())
object();
if (!(current instanceof Map))
return failure("current node is not an Object", key);
if (!o(current).containsKey(key)) {
if (readonly)
return failure("current Object have no key named " + key, key);
stack.add(current);
path.add(key);
current = null;
missingKey = key;
return this;
}
Object next = o(current).get(key);
stack.add(current);
path.add(key);
current = next;
return this;
}
public Object get(String key) {
if (failure)
return this;
if (!isObject())
object();
if (!(current instanceof Map))
return failure("current node is not an Object", key);
return o(current).get(key);
}
public Object get(int index) {
if (failure)
return this;
if (!isArray())
array();
if (!(current instanceof List))
return failure("current node is not an List", index);
return a(current).get(index);
}
public JSONNavi set(String key, String value) {
object();
if (failure)
return this;
o(current).put(key, value);
return this;
}
public JSONNavi set(String key, Number value) {
object();
if (failure)
return this;
o(current).put(key, value);
return this;
}
/**
* write an value in the current object
*
* @param key
* key to access
* @param value
* new value
* @return this
*/
public JSONNavi set(String key, long value) {
return set(key, Long.valueOf(value));
}
/**
* write an value in the current object
*
* @param key
* key to access
* @param value
* new value
* @return this
*/
public JSONNavi set(String key, int value) {
return set(key, Integer.valueOf(value));
}
/**
* write an value in the current object
*
* @param key
* key to access
* @param value
* new value
* @return this
*/
public JSONNavi set(String key, double value) {
return set(key, Double.valueOf(value));
}
/**
* write an value in the current object
*
* @param key
* key to access
* @param value
* new value
* @return this
*/
public JSONNavi set(String key, float value) {
return set(key, Float.valueOf(value));
}
/**
* add value to the current arrays
*
* @param values
* to add
* @return this
*/
public JSONNavi add(Object... values) {
array();
if (failure)
return this;
List list = a(current);
for (Object o : values)
list.add(o);
return this;
}
/**
* get the current object value as String if the current Object is null
* return null.
*
* @return value as string
*/
public String asString() {
if (current == null)
return null;
if (current instanceof String)
return (String) current;
return current.toString();
}
/**
* get the current value as double if the current Object is null return
* Double.NaN
*
* @return value as double
*/
public double asDouble() {
if (current instanceof Number)
return ((Number) current).doubleValue();
return Double.NaN;
}
/**
* get the current object value as Double if the current Double can not be
* cast as Integer return null.
*
* @return value as Double
*/
public Double asDoubleObj() {
if (current == null)
return null;
if (current instanceof Number) {
if (current instanceof Double)
return (Double) current;
return Double.valueOf(((Number) current).doubleValue());
}
return Double.NaN;
}
/**
* get the current value as float if the current Object is null return
* Float.NaN
*
* @return value as float
*/
public float asFloat() {
if (current instanceof Number)
return ((Number) current).floatValue();
return Float.NaN;
}
/**
* get the current object value as Float if the current Float can not be
* cast as Integer return null.
*/
public Float asFloatObj() {
if (current == null)
return null;
if (current instanceof Number) {
if (current instanceof Float)
return (Float) current;
return Float.valueOf(((Number) current).floatValue());
}
return Float.NaN;
}
/**
* get the current value as int if the current Object is null return 0
*
* @return value as Int
*/
public int asInt() {
if (current instanceof Number)
return ((Number) current).intValue();
return 0;
}
/**
* get the current object value as Integer if the current Object can not be
* cast as Integer return null.
* @return the current node value as an Integer
*/
public Integer asIntegerObj() {
if (current == null)
return null;
if (current instanceof Number) {
if (current instanceof Integer)
return (Integer) current;
if (current instanceof Long) {
Long l = (Long) current;
if (l.longValue() == l.intValue()) {
return Integer.valueOf(l.intValue());
}
}
return null;
}
return null;
}
/**
* get the current value as long if the current Object is null return 0
*
* @return value as long
*/
public long asLong() {
if (current instanceof Number)
return ((Number) current).longValue();
return 0L;
}
/**
* get the current object value as Long if the current Object can not be
* cast as Long return null.
*
* @return value as Long
*/
public Long asLongObj() {
if (current == null)
return null;
if (current instanceof Number) {
if (current instanceof Long)
return (Long) current;
if (current instanceof Integer)
return Long.valueOf(((Number) current).longValue());
return null;
}
return null;
}
/**
* get the current value as boolean if the current Object is null or is not
* a boolean return false
*
* @return boolean
*/
public boolean asBoolean() {
if (current instanceof Boolean)
return ((Boolean) current).booleanValue();
return false;
}
/**
* get the current object value as Boolean if the current Object is not a
* Boolean return null.
*
* @return Boolean object
*/
public Boolean asBooleanObj() {
if (current == null)
return null;
if (current instanceof Boolean)
return (Boolean) current;
return null;
}
/**
* Set current value as Json Object You can also skip this call, Objects can
* be create automatically.
* @return the current node as an object
*/
@SuppressWarnings("unchecked")
public JSONNavi object() {
if (failure)
return this;
if (current == null && readonly)
failure("Can not create Object child in readonly", null);
if (current != null) {
if (isObject())
return this;
if (isArray())
failure("can not use Object feature on Array.", null);
failure("Can not use current position as Object", null);
} else {
current = mapper.createObject();
}
if (root == null)
root = (T) current;
else
store();
return this;
}
/**
* Set current value as Json Array You can also skip this call Arrays can be
* create automatically.
*
* @return the current node as an array
*/
@SuppressWarnings("unchecked")
public JSONNavi array() {
if (failure)
return this;
if (current == null && readonly)
failure("Can not create Array child in readonly", null);
if (current != null) {
if (isArray())
return this;
if (isObject())
failure("can not use Object feature on Array.", null);
failure("Can not use current position as Object", null);
} else {
current = mapper.createArray();
}
if (root == null)
root = (T) current;
else
store();
return this;
}
/**
* set current value as Number
* @param num new value for the current node
* @return this for code chaining
*/
public JSONNavi set(Number num) {
if (failure)
return this;
current = num;
store();
return this;
}
/**
* set current value as Boolean
* @param bool new value for the current node
*
* @return this for code chaining
*/
public JSONNavi set(Boolean bool) {
if (failure)
return this;
current = bool;
store();
return this;
}
/**
* set current value as String
* @param text text value
*
* @return this for code chaining
*/
public JSONNavi set(String text) {
if (failure)
return this;
current = text;
store();
return this;
}
public T getRoot() {
return root;
}
/**
* internal store current Object in current non existing localization
*/
private void store() {
Object parent = stack.peek();
if (isObject(parent))
o(parent).put((String) missingKey, current);
else if (isArray(parent)) {
int index = ((Number) missingKey).intValue();
List lst = a(parent);
while (lst.size() <= index)
lst.add(null);
lst.set(index, current);
}
}
/**
* is the current node is an array
*
* @return true if the current node is an array
*/
public boolean isArray() {
return isArray(current);
}
/**
* is the current node is an object
*
* @return true if the current node is an object
*/
public boolean isObject() {
return isObject(current);
}
/**
* check if Object is an Array
*
* @return true if the object is an array
*/
private boolean isArray(Object obj) {
if (obj == null)
return false;
return (obj instanceof List);
}
/**
* check if Object is an Map
* @return true if the object node is an object
*/
private boolean isObject(Object obj) {
if (obj == null)
return false;
return (obj instanceof Map);
}
/**
* internal cast to List
* @return casted object
*/
@SuppressWarnings("unchecked")
private List a(Object obj) {
return (List) obj;
}
/**
* internal cast to Map
*/
@SuppressWarnings("unchecked")
private Map o(Object obj) {
return (Map) obj;
}
/**
* Access to the index position.
*
* If index is less than 0 access element index from the end like in python.
*
* @param index
* 0 based desired position in Array
*/
public JSONNavi> at(int index) {
if (failure)
return this;
if (!(current instanceof List))
return failure("current node is not an Array", index);
@SuppressWarnings("unchecked")
List lst = ((List) current);
if (index < 0) {
index = lst.size() + index;
if (index < 0)
index = 0;
}
if (index >= lst.size())
if (readonly)
return failure("Out of bound exception for index", index);
else {
stack.add(current);
path.add(index);
current = null;
missingKey = index;
return this;
}
Object next = lst.get(index);
stack.add(current);
path.add(index);
current = next;
return this;
}
/**
* Access to last + 1 the index position.
*
* this method can only be used in writing mode.
*/
public JSONNavi> atNext() {
if (failure)
return this;
if (!(current instanceof List))
return failure("current node is not an Array", null);
@SuppressWarnings("unchecked")
List lst = ((List) current);
return at(lst.size());
}
/**
* call up() level times.
*
* @param level
* number of parent move.
*/
public JSONNavi> up(int level) {
while (level-- > 0) {
if (stack.size() > 0) {
current = stack.pop();
path.pop();
} else
break;
}
return this;
}
/**
* Move one level up in Json tree. if no more level up is available the
* statement had no effect.
*/
public JSONNavi> up() {
if (stack.size() > 0) {
current = stack.pop();
path.pop();
}
return this;
}
private final static JSONStyle ERROR_COMPRESS = new JSONStyle(JSONStyle.FLAG_PROTECT_4WEB);
/**
* return the Object as a Json String
*/
public String toString() {
if (failure)
return JSONValue.toJSONString(failureMessage, ERROR_COMPRESS);
return JSONValue.toJSONString(root);
}
/**
* return the Object as a Json String
*
* @param compression
*/
public String toString(JSONStyle compression) {
if (failure)
return JSONValue.toJSONString(failureMessage, compression);
return JSONValue.toJSONString(root, compression);
}
/**
* Internally log errors.
*/
private JSONNavi> failure(String err, Object jPathPostfix) {
failure = true;
StringBuilder sb = new StringBuilder();
sb.append("Error: ");
sb.append(err);
sb.append(" at ");
sb.append(getJPath());
if (jPathPostfix != null)
if (jPathPostfix instanceof Integer)
sb.append('[').append(jPathPostfix).append(']');
else
sb.append('/').append(jPathPostfix);
this.failureMessage = sb.toString();
return this;
}
/**
* @return JPath to the current position
*/
public String getJPath() {
StringBuilder sb = new StringBuilder();
for (Object o : path) {
if (o instanceof String)
sb.append('/').append(o.toString());
else
sb.append('[').append(o.toString()).append(']');
}
return sb.toString();
}
}