content: package eu.amirs;
  
  import org.json.JSONArray;
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.util.*;
  
  /**
   * Created by amirkhorsandi on 3/3/17.
   */
  
  public class JSON {
  
      private JSONObject jsObj;
      private JSONArray jsArr;
      private Object value;
  
  
      public JSON(Object jsonString) {
  
          if (ArrayList.class.isInstance(jsonString))
              jsonString = new JSONArray((ArrayList) jsonString);
  
  
          if (jsonString == null) {
              value = null;
          } else if (jsonString.toString().trim().startsWith("{")) {
              //json object
              try {
                  jsObj = new JSONObject(jsonString.toString());
              } catch (JSONException e) {
                  e.printStackTrace();
              }
          } else if (jsonString.toString().trim().startsWith("[")) {
              //json array
              try {
                  jsArr = new JSONArray(jsonString.toString());
              } catch (JSONException e) {
                  e.printStackTrace();
              }
  
          } else
              value = jsonString;
  
  
      }
  
  
      @Override
      public String toString() {
  
          if (isNull()) return "";
          return this.value().toString();
      }
  
      public int count() {
  
          if (jsObj != null) return jsObj.length();
          if (jsArr != null) return jsArr.length();
          return 0;
      }
  
      public JSON key(String keyStr) {
  
  
          if (jsObj == null) return new JSON(null);
  
  
          try {
  
              Object obj = jsObj.get(keyStr);
              if (obj != null)
                  return new JSON(obj);
  
          } catch (JSONException e) {
              e.printStackTrace();
          }
  
          return new JSON(null);
      }
  
      public JSON index(int index) {
  
  
          if (jsArr == null) return new JSON(null);
  
          try {
              return new JSON(jsArr.get(index));
          } catch (JSONException e) {
              e.printStackTrace();
          }
  
          return new JSON(null);
  
      }
  
  
      public String  stringValue() {
  
          if (this.value() == null)
              return "";
          if (isNull())
              return "";
  
          return String.valueOf(this.value());
  
      }
  
      public int intValue() {
  
          if (this.value() == null) return 0;
  
          try {
              return Integer.valueOf(this.value().toString());
          } catch (java.lang.NumberFormatException e) {
              return 0;
          }
      }
  
      public long longValue() {
  
          if (this.value() == null) return 0;
  
          try {
              return Long.valueOf(this.value().toString());
          } catch (java.lang.NumberFormatException e) {
              return 0;
          }
      }
  
  
      public Double doubleValue() {
  
          if (this.value() == null) return 0.0;
  
          try {
              return Double.valueOf(this.value().toString());
          } catch (java.lang.NumberFormatException e) {
              return 0.0;
          }
      }
  
      public boolean booleanValue() {
  
          if (this.value() == null) return false;
  
          return this.stringValue().equals("true");
  
      }
  
      public Object value() {
  
          if (nullableValue() != null) return nullableValue();
  
          return new JSON(null);
      }
  
  
      public boolean isNull() {
  
          if (value == null && jsArr == null && jsObj == null)
              return true;
          if (String.valueOf(this.value()).equals("null"))
              return true;
  
          return false;
  
      }
  
      private Object nullableValue() {
  
          if (value != null) return value;
  
          if (jsObj != null) return jsObj.toString();
  
          if (jsArr != null) return jsArr.toString();
  
  
          return null;
      }
  
  
      public boolean exist() {
          return nullableValue() != null;
      }
  
  
      public JSONObject getJsonObject() {
          return jsObj;
      }
  
      public JSONArray getJsonArray() {
          return jsArr;
      }
  
  
      public void removeWithKey(String Key) {
  
          if (Key == null)
              return;
  
          JSONObject jsonObject = this.getJsonObject();
  
          if (jsonObject == null)
              return;
  
          jsonObject.remove(Key);
  
          this.jsObj = jsonObject;
      }
  
      public void addEditWithKey(String Key, Object Object) {
  
          if (Object == null || Key == null)
              return;
  
          JSONObject jsonObject = this.getJsonObject();
  
          if (jsonObject == null)
              return;
  
  
          Object normalizedObject = Object;
  
  
          if (JSON.class.isInstance(Object)) {
              if (((JSON) Object).getJsonArray() != null)
                  normalizedObject = ((JSON) Object).getJsonArray();
              else if (((JSON) Object).getJsonObject() != null)
                  normalizedObject = ((JSON) Object).getJsonObject();
              else
                  normalizedObject = ((JSON) Object).value();
          }
  
  
          try {
              jsonObject.putOpt(Key, normalizedObject);
          } catch (JSONException e) {
              e.printStackTrace();
          }
          this.jsObj = jsonObject;
  
      }
  
  
      public void addWithIndex(Object inputObject, int index) {
  
  
          if (inputObject == null)
              return;
  
          JSONArray jsonArr = this.getJsonArray();
  
          if (jsonArr == null)
              return;
  
          try {
  
              if (JSON.class.isInstance(inputObject)) {
                  if (((JSON) inputObject).getJsonArray() != null) {
  
                      if (index == -1)
                          jsonArr.put(((JSON) inputObject).getJsonArray());
                      else
                          jsonArr.put(index, ((JSON) inputObject).getJsonArray());
  
                  } else if (((JSON) inputObject).getJsonObject() != null) {
  
                      if (index == -1)
                          jsonArr.put(((JSON) inputObject).getJsonObject());
                      else
                          jsonArr.put(index, ((JSON) inputObject).getJsonObject());
  
                  } else {
                      if (index == -1)
                          jsonArr.put(((JSON) inputObject).value());
                      else
                          jsonArr.put(index, ((JSON) inputObject).value());
                  }
  
              } else {
                  if (index == -1)
                      jsonArr.put(inputObject);
                  else if(index > -1)
                      jsonArr.put(index, inputObject);
              }
  
          } catch (JSONException e) {
              e.printStackTrace();
          }
  
  
  
          this.jsArr = jsonArr;
      }
  
      public void add(Object inputObject) {
          addWithIndex(inputObject, -1);
      }
  
  
      public void removeWithIndex(int index) {
  
          JSONArray jsonArr = this.getJsonArray();
  
          if (jsonArr == null)
              return;
  
          JSONArray newJsonArr = new JSONArray();
  
          for (int i = 0; i < jsonArr.length(); i++) {
  
  
              try {
                  if (i != index) {
                      newJsonArr.put(jsonArr.get(i));
                  }
  
              } catch (JSONException e) {
                  e.printStackTrace();
              }
  
          }
  
  
          this.jsArr = newJsonArr;
  
      }
  
  
      public void remove(Object inputObject) {
  
          if (inputObject == null)
              return;
  
          JSONArray jsonArr = this.getJsonArray();
  
          if (jsonArr == null)
              return;
  
          JSONArray newJsonArr = new JSONArray();
  
          for (int i = 0; i < jsonArr.length(); i++) {
  
  
              try {
                  if (JSONObject.class.isInstance(inputObject) && JSONObject.class.isInstance(jsonArr.get(i))) {
  
                      if (!jsonObjectComparesEqual((JSONObject)jsonArr.get(i), (JSONObject)inputObject, null, null) ) {
                          newJsonArr.put(jsonArr.get(i));
                      }
  
                  } else {
                      if (!jsonArr.get(i).equals(inputObject)) {
                          newJsonArr.put(jsonArr.get(i));
                      }
  
                  }
              } catch (JSONException e) {
                  e.printStackTrace();
              }
  
  
          }
  
  
          this.jsArr = newJsonArr;
      }
  
  
      public static JSON create(Object object) {
  
          return new JSON(object.toString());
      }
  
  
      public static JSONObject dic(Object... values) {
  
          JSONObject mainDic = new JSONObject();
          for (int i = 0; i < values.length; i += 2) {
  
              try {
  
                  Object valueObject = values[i + 1];
  
                  if (JSON.class.isInstance(valueObject)) {
  
                      if (((JSON) valueObject).getJsonArray() != null)
                          valueObject = ((JSON) valueObject).getJsonArray();
  
                      else if (((JSON) valueObject).getJsonObject() != null)
                          valueObject = ((JSON) valueObject).getJsonObject();
                  }
  
                  mainDic.put((String) values[i], valueObject == null ? JSONObject.NULL:valueObject);
              } catch (JSONException e) {
                  e.printStackTrace();
              }
          }
          return mainDic;
      }
  
  
      public static JSONArray array(Object... values) {
  
          JSONArray mainList = new JSONArray();
          for (Object obj : values)
              mainList.put(obj);
          return mainList;
      }
  
  
  
  
      public static boolean jsonObjectComparesEqual(JSONObject x, JSONObject y, Collection<String> only, Collection<String> except) {
          Set<String> keys = keySet(x);
          keys.addAll(keySet(y));
          if (only != null) {
              keys.retainAll(only);
          }
          if (except != null) {
              keys.removeAll(except);
          }
          for (String s : keys) {
              Object a = null, b = null;
              try {
                  a = x.get(s);
              } catch (JSONException e) {
              }
              try {
                  b = x.get(s);
              } catch (JSONException e) {
              }
              if (a != null) {
                  if (!a.equals(b)) {
                      return false;
                  }
              } else if (b != null) {
                  if (!b.equals(a)) {
                      return false;
                  }
              }
          }
          return true;
      }
      private static Set<String> keySet(JSONObject j) {
          Set<String> res = new TreeSet<String>();
          for (String s : new AsIterable<String>(j.keys())) {
              res.add(s);
          }
          return res;
      }
  
      private static class AsIterable<T> implements Iterable<T> {
          private Iterator<T> iterator;
          public AsIterable(Iterator<T> iterator) {
              this.iterator = iterator;
          }
          public Iterator<T> iterator() {
              return iterator;
          }
      }
  
  }
  