Есть ли способ клонировать экземпляр org.json.JSONObject
, не строгая его и перерисовывая результат?
Неверная копия будет приемлемой.
Есть ли способ клонировать экземпляр org.json.JSONObject
, не строгая его и перерисовывая результат?
Неверная копия будет приемлемой.
Используйте конструктор public JSONObject(JSONObject jo, java.lang.String[] names)
и public static java.lang.String[] getNames(JSONObject jo)
.
JSONObject copy = new JSONObject(original, JSONObject.getNames(original));
Самый простой (и невероятно медленный и неэффективный) способ сделать это
JSONObject clone = new JSONObject(original.toString());
Не удалось найти существующий метод глубокого клонирования для com.google.gwt.json.client.JSONObject, но реализация должна быть немного строк кода, например:
public static JSONValue deepClone(JSONValue jsonValue){
JSONString string = jsonValue.isString();
if (string != null){return new JSONString(string.stringValue());}
JSONBoolean aBoolean = jsonValue.isBoolean();
if (aBoolean != null){return JSONBoolean.getInstance(aBoolean.booleanValue());}
JSONNull aNull = jsonValue.isNull();
if (aNull != null){return JSONNull.getInstance();}
JSONNumber number = jsonValue.isNumber();
if (number!=null){return new JSONNumber(number.doubleValue());}
JSONObject jsonObject = jsonValue.isObject();
if (jsonObject!=null){
JSONObject clonedObject = new JSONObject();
for (String key : jsonObject.keySet()){
clonedObject.put(key, deepClone(jsonObject.get(key)));
}
return clonedObject;
}
JSONArray array = jsonValue.isArray();
if (array != null){
JSONArray clonedArray = new JSONArray();
for (int i=0 ; i < array.size() ; ++i){
clonedArray.set(i, deepClone(array.get(i)));
}
return clonedArray;
}
throw new IllegalStateException();
}
* Примечание: * Я еще не тестировал его!
Причина $JSONObject.getNames(original)
недоступна в android,
вы можете сделать это с помощью:
public JSONObject shallowCopy(JSONObject original) {
JSONObject copy = new JSONObject();
for ( Iterator<String> iterator = original.keys(); iterator.hasNext(); ) {
String key = iterator.next();
JSONObject value = original.optJSONObject(key);
try {
copy.put(key, value);
} catch ( JSONException e ) {
//TODO process exception
}
}
return copy;
}
Но помните, что это не глубокая копия.
Для разработчиков Android самое простое решение без использования .getNames
:
JSONObject copy = new JSONObject();
for (Object key : original.keySet()) {
Object value = original.get(key);
copy.put(key, value);
}
Примечание. Это только поверхностная копия
В случае, если кто-то приходит сюда искать глубокий клон для org.google.gson, так как они не раскрывают свой метод deepClone(), это то, что я придумал...
public static JsonElement deepClone(JsonElement el){
if (el.isJsonPrimitive() || el.isJsonNull())
return el;
if (el.isJsonArray()) {
JsonArray array = new JsonArray();
for(JsonElement arrayEl: el.getAsJsonArray())
array.add(deepClone(arrayEl));
return array;
}
if(el.isJsonObject()) {
JsonObject obj = new JsonObject();
for (Map.Entry<String, JsonElement> entry : el.getAsJsonObject().entrySet()) {
obj.add(entry.getKey(), deepClone(entry.getValue()));
}
return obj;
}
throw new IllegalArgumentException("JsonElement type " + el.getClass().getName());
}
И вот несколько способов объединить два JsonObject's
public static JsonObject merge(String overrideJson, JsonObject defaultObj) {
return mergeInto((JsonObject)new JsonParser().parse(overrideJson), defaultObj);
}
public static JsonObject merge(JsonObject overrideObj, JsonObject defaultObj) {
return mergeOverride((JsonObject)deepClone(defaultObj), overrideObj);
}
public static JsonObject mergeOverride(JsonObject targetObj, JsonObject overrideObj) {
for (Map.Entry<String, JsonElement> entry : overrideObj.entrySet())
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
return targetObj;
}
public static JsonObject mergeInto(JsonObject targetObj, JsonObject defaultObj) {
for (Map.Entry<String, JsonElement> entry : defaultObj.entrySet()) {
if (targetObj.has(entry.getKey()) == false)
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
}
return targetObj;
}