feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
commit
bfe27fdc08
104 files changed
+58750
No files matched your search
Whitespace-only changes.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,858 @@
|
||||
"""
|
||||
Java JSON standard library APIs implemented in Python.
|
||||
org.json package - JSONObject, JSONArray, JSONTokener, JSONStringer, JSONWriter, etc.
|
||||
"""
|
||||
|
||||
from .._core import Stub
|
||||
import json as _json
|
||||
|
||||
__all__ = [
|
||||
"JSONObject", "JSONArray", "JSONTokener",
|
||||
"JSONStringer", "JSONWriter", "JSONException", "JSONPointer",
|
||||
"JSONPointerBuilder",
|
||||
]
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONException
|
||||
# ============================================================
|
||||
|
||||
class JSONException(Exception):
|
||||
def __init__(self, *args):
|
||||
if len(args) == 1 and isinstance(args[0], Exception):
|
||||
super().__init__(str(args[0]))
|
||||
self._cause = args[0]
|
||||
else:
|
||||
super().__init__(*args)
|
||||
self._cause = None
|
||||
|
||||
def getCause(self):
|
||||
return self._cause
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONObject.NULL
|
||||
# ============================================================
|
||||
|
||||
class _JSONNull(Stub):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def equals(self, other):
|
||||
return other is None or isinstance(other, _JSONNull)
|
||||
|
||||
def hashCode(self):
|
||||
return 0
|
||||
|
||||
def toString(self):
|
||||
return "null"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONObject
|
||||
# ============================================================
|
||||
|
||||
class JSONObject(Stub):
|
||||
NULL = _JSONNull()
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._map = {}
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, str):
|
||||
tokener = JSONTokener(arg)
|
||||
obj = tokener.nextValue()
|
||||
if isinstance(obj, JSONObject):
|
||||
self._map = obj._map
|
||||
else:
|
||||
raise JSONException("String is not a JSONObject")
|
||||
elif isinstance(arg, dict):
|
||||
for k, v in arg.items():
|
||||
self._map[str(k)] = JSONObject._wrap(v)
|
||||
elif isinstance(arg, JSONObject):
|
||||
names = None
|
||||
self._map = dict(arg._map)
|
||||
|
||||
def _wrap(val):
|
||||
if val is None:
|
||||
return JSONObject.NULL
|
||||
if isinstance(val, (bool, int, float)):
|
||||
return val
|
||||
if isinstance(val, str):
|
||||
return val
|
||||
if isinstance(val, (list, tuple)):
|
||||
arr = JSONArray()
|
||||
for item in val:
|
||||
arr.put(JSONObject._wrap(item))
|
||||
return arr
|
||||
if isinstance(val, dict):
|
||||
obj = JSONObject()
|
||||
for k, v in val.items():
|
||||
obj.put(str(k), JSONObject._wrap(v))
|
||||
return obj
|
||||
if isinstance(val, JSONObject) or isinstance(val, JSONArray):
|
||||
return val
|
||||
return val
|
||||
|
||||
def put(self, key, value):
|
||||
self._map[str(key)] = JSONObject._wrap(value)
|
||||
return self
|
||||
|
||||
def accumulate(self, key, value):
|
||||
k = str(key)
|
||||
current = self._map.get(k)
|
||||
if current is None:
|
||||
arr = JSONArray()
|
||||
arr.put(value)
|
||||
self._map[k] = arr
|
||||
elif isinstance(current, JSONArray):
|
||||
current.put(value)
|
||||
else:
|
||||
arr = JSONArray()
|
||||
arr.put(current)
|
||||
arr.put(value)
|
||||
self._map[k] = arr
|
||||
return self
|
||||
|
||||
def get(self, key):
|
||||
k = str(key)
|
||||
if k not in self._map:
|
||||
raise JSONException(f"JSONObject[\"{k}\"] not found")
|
||||
val = self._map[k]
|
||||
if val is JSONObject.NULL:
|
||||
raise JSONException(f"JSONObject[\"{k}\"] is null")
|
||||
return val
|
||||
|
||||
def opt(self, key, default=None):
|
||||
k = str(key)
|
||||
val = self._map.get(k)
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return default
|
||||
return val
|
||||
|
||||
def getString(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, str):
|
||||
return val
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a string")
|
||||
|
||||
def getInt(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not an int")
|
||||
|
||||
def getLong(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a long")
|
||||
|
||||
def getDouble(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, (int, float)):
|
||||
return float(val)
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a double")
|
||||
|
||||
def getBoolean(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
if val == "true":
|
||||
return True
|
||||
if val == "false":
|
||||
return False
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a boolean")
|
||||
|
||||
def getJSONArray(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, JSONArray):
|
||||
return val
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a JSONArray")
|
||||
|
||||
def getJSONObject(self, key):
|
||||
val = self.get(key)
|
||||
if isinstance(val, JSONObject):
|
||||
return val
|
||||
raise JSONException(f"JSONObject[\"{key}\"] is not a JSONObject")
|
||||
|
||||
def optString(self, key, default=""):
|
||||
val = self.opt(key)
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return default
|
||||
return str(val)
|
||||
|
||||
def optInt(self, key, default=0):
|
||||
val = self.opt(key)
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return default
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
try:
|
||||
return int(val)
|
||||
except (ValueError, TypeError):
|
||||
return default
|
||||
|
||||
def optLong(self, key, default=0):
|
||||
return self.optInt(key, default)
|
||||
|
||||
def optDouble(self, key, default=0.0):
|
||||
val = self.opt(key)
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return default
|
||||
if isinstance(val, (int, float)):
|
||||
return float(val)
|
||||
try:
|
||||
return float(val)
|
||||
except (ValueError, TypeError):
|
||||
return default
|
||||
|
||||
def optBoolean(self, key, default=False):
|
||||
val = self.opt(key)
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return default
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
if isinstance(val, str):
|
||||
return val.lower() == "true"
|
||||
return default
|
||||
|
||||
def optJSONArray(self, key):
|
||||
val = self.opt(key)
|
||||
if isinstance(val, JSONArray):
|
||||
return val
|
||||
return None
|
||||
|
||||
def optJSONObject(self, key):
|
||||
val = self.opt(key)
|
||||
if isinstance(val, JSONObject):
|
||||
return val
|
||||
return None
|
||||
|
||||
def has(self, key):
|
||||
return str(key) in self._map
|
||||
|
||||
def remove(self, key):
|
||||
k = str(key)
|
||||
if k in self._map:
|
||||
del self._map[k]
|
||||
|
||||
def keys(self):
|
||||
return iter(self._map.keys())
|
||||
|
||||
def names(self):
|
||||
if not self._map:
|
||||
return None
|
||||
arr = JSONArray()
|
||||
for k in self._map:
|
||||
arr.put(k)
|
||||
return arr
|
||||
|
||||
def length(self):
|
||||
return len(self._map)
|
||||
|
||||
def toString(self, indent_factor=None):
|
||||
if indent_factor is None:
|
||||
return self._to_json_string()
|
||||
return self._to_json_pretty(indent_factor)
|
||||
|
||||
def _to_json_string(self):
|
||||
parts = ["{"]
|
||||
for i, (k, v) in enumerate(self._map.items()):
|
||||
parts.append('"' + k + '": ' + JSONObject._value_to_string(v))
|
||||
if i < len(self._map) - 1:
|
||||
parts.append(", ")
|
||||
parts.append("}")
|
||||
return "".join(parts)
|
||||
|
||||
def _to_json_pretty(self, indent):
|
||||
parts = ["{"]
|
||||
for i, (k, v) in enumerate(self._map.items()):
|
||||
parts.append("\n" + " " * indent + '"' + k + '": ' + JSONObject._value_to_string(v))
|
||||
if i < len(self._map) - 1:
|
||||
parts.append(",")
|
||||
parts.append("\n}")
|
||||
return "".join(parts)
|
||||
|
||||
def _value_to_string(val):
|
||||
if val is None or val is JSONObject.NULL:
|
||||
return "null"
|
||||
if isinstance(val, bool):
|
||||
return "true" if val else "false"
|
||||
if isinstance(val, (int, float)):
|
||||
return str(val)
|
||||
if isinstance(val, str):
|
||||
return _json.dumps(val)
|
||||
if isinstance(val, JSONObject):
|
||||
return val._to_json_string()
|
||||
if isinstance(val, JSONArray):
|
||||
return val._to_json_string()
|
||||
return str(val)
|
||||
|
||||
def toMap(self):
|
||||
result = {}
|
||||
for k, v in self._map.items():
|
||||
if isinstance(v, JSONObject):
|
||||
result[k] = v.toMap()
|
||||
elif isinstance(v, JSONArray):
|
||||
result[k] = v.toList()
|
||||
elif v is JSONObject.NULL:
|
||||
result[k] = None
|
||||
else:
|
||||
result[k] = v
|
||||
return result
|
||||
|
||||
def write(self, writer):
|
||||
writer._write(self._to_json_string())
|
||||
|
||||
def toJSONArray(self, names):
|
||||
if names is None or names.length() == 0:
|
||||
return None
|
||||
arr = JSONArray()
|
||||
for i in range(names.length()):
|
||||
arr.put(self.opt(names.getString(i)))
|
||||
return arr
|
||||
|
||||
def hashCode(self):
|
||||
return hash(frozenset(self._map.items()))
|
||||
|
||||
def equals(self, other):
|
||||
if isinstance(other, JSONObject):
|
||||
return self._map == other._map
|
||||
return False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONArray
|
||||
# ============================================================
|
||||
|
||||
class JSONArray(Stub):
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._list = []
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, str):
|
||||
tokener = JSONTokener(arg)
|
||||
val = tokener.nextValue()
|
||||
if isinstance(val, JSONArray):
|
||||
self._list = val._list
|
||||
else:
|
||||
raise JSONException("String is not a JSONArray")
|
||||
elif isinstance(arg, (list, tuple)):
|
||||
for item in arg:
|
||||
self.put(JSONObject._wrap(item))
|
||||
|
||||
def put(self, *args):
|
||||
if len(args) == 1:
|
||||
self._list.append(JSONObject._wrap(args[0]))
|
||||
elif len(args) == 2:
|
||||
index, value = args
|
||||
while len(self._list) <= index:
|
||||
self._list.append(None)
|
||||
self._list[index] = JSONObject._wrap(value)
|
||||
return self
|
||||
|
||||
def get(self, index):
|
||||
if index < 0 or index >= len(self._list):
|
||||
raise JSONException(f"JSONArray[{index}] not found")
|
||||
val = self._list[index]
|
||||
if val is JSONObject.NULL:
|
||||
raise JSONException(f"JSONArray[{index}] is null")
|
||||
return val
|
||||
|
||||
def getString(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, str):
|
||||
return val
|
||||
raise JSONException(f"JSONArray[{index}] is not a string")
|
||||
|
||||
def getInt(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
raise JSONException(f"JSONArray[{index}] is not an int")
|
||||
|
||||
def getLong(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
raise JSONException(f"JSONArray[{index}] is not a long")
|
||||
|
||||
def getDouble(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, (int, float)):
|
||||
return float(val)
|
||||
raise JSONException(f"JSONArray[{index}] is not a double")
|
||||
|
||||
def getBoolean(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
if val == "true":
|
||||
return True
|
||||
if val == "false":
|
||||
return False
|
||||
raise JSONException(f"JSONArray[{index}] is not a boolean")
|
||||
|
||||
def getJSONArray(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, JSONArray):
|
||||
return val
|
||||
raise JSONException(f"JSONArray[{index}] is not a JSONArray")
|
||||
|
||||
def getJSONObject(self, index):
|
||||
val = self.get(index)
|
||||
if isinstance(val, JSONObject):
|
||||
return val
|
||||
raise JSONException(f"JSONArray[{index}] is not a JSONObject")
|
||||
|
||||
def opt(self, index, default=None):
|
||||
if index < 0 or index >= len(self._list):
|
||||
return default
|
||||
val = self._list[index]
|
||||
if val is JSONObject.NULL:
|
||||
return default
|
||||
return val
|
||||
|
||||
def optString(self, index, default=""):
|
||||
val = self.opt(index)
|
||||
if val is None:
|
||||
return default
|
||||
return str(val)
|
||||
|
||||
def optInt(self, index, default=0):
|
||||
val = self.opt(index)
|
||||
if val is None:
|
||||
return default
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
try:
|
||||
return int(val)
|
||||
except (ValueError, TypeError):
|
||||
return default
|
||||
|
||||
def optLong(self, index, default=0):
|
||||
return self.optInt(index, default)
|
||||
|
||||
def optDouble(self, index, default=0.0):
|
||||
val = self.opt(index)
|
||||
if val is None:
|
||||
return default
|
||||
if isinstance(val, (int, float)):
|
||||
return float(val)
|
||||
try:
|
||||
return float(val)
|
||||
except (ValueError, TypeError):
|
||||
return default
|
||||
|
||||
def optBoolean(self, index, default=False):
|
||||
val = self.opt(index)
|
||||
if val is None:
|
||||
return default
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
if isinstance(val, str):
|
||||
return val.lower() == "true"
|
||||
return default
|
||||
|
||||
def optJSONArray(self, index):
|
||||
val = self.opt(index)
|
||||
if isinstance(val, JSONArray):
|
||||
return val
|
||||
return None
|
||||
|
||||
def optJSONObject(self, index):
|
||||
val = self.opt(index)
|
||||
if isinstance(val, JSONObject):
|
||||
return val
|
||||
return None
|
||||
|
||||
def remove(self, index):
|
||||
if 0 <= index < len(self._list):
|
||||
return self._list.pop(index)
|
||||
return None
|
||||
|
||||
def length(self):
|
||||
return len(self._list)
|
||||
|
||||
def isNull(self, index):
|
||||
if 0 <= index < len(self._list):
|
||||
return self._list[index] is JSONObject.NULL or self._list[index] is None
|
||||
return True
|
||||
|
||||
def toString(self, indent_factor=None):
|
||||
if indent_factor is None:
|
||||
return self._to_json_string()
|
||||
return self._to_json_pretty(indent_factor)
|
||||
|
||||
def _to_json_string(self):
|
||||
parts = ["["]
|
||||
for i, v in enumerate(self._list):
|
||||
parts.append(JSONObject._value_to_string(v))
|
||||
if i < len(self._list) - 1:
|
||||
parts.append(", ")
|
||||
parts.append("]")
|
||||
return "".join(parts)
|
||||
|
||||
def _to_json_pretty(self, indent):
|
||||
parts = ["["]
|
||||
for i, v in enumerate(self._list):
|
||||
parts.append("\n" + " " * indent + JSONObject._value_to_string(v))
|
||||
if i < len(self._list) - 1:
|
||||
parts.append(",")
|
||||
parts.append("\n]")
|
||||
return "".join(parts)
|
||||
|
||||
def toList(self):
|
||||
result = []
|
||||
for v in self._list:
|
||||
if isinstance(v, JSONObject):
|
||||
result.append(v.toMap())
|
||||
elif isinstance(v, JSONArray):
|
||||
result.append(v.toList())
|
||||
elif v is JSONObject.NULL:
|
||||
result.append(None)
|
||||
else:
|
||||
result.append(v)
|
||||
return result
|
||||
|
||||
def join(self, separator):
|
||||
parts = []
|
||||
for v in self._list:
|
||||
parts.append(JSONObject._value_to_string(v))
|
||||
return separator.join(parts)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONTokener
|
||||
# ============================================================
|
||||
|
||||
class JSONTokener(Stub):
|
||||
def __init__(self, source):
|
||||
super().__init__()
|
||||
if hasattr(source, "read"):
|
||||
self._source = source.read()
|
||||
else:
|
||||
self._source = str(source)
|
||||
self._index = 0
|
||||
|
||||
def nextValue(self):
|
||||
self._skipWhitespace()
|
||||
if self._index >= len(self._source):
|
||||
raise JSONException("Unexpected end of input")
|
||||
ch = self._source[self._index]
|
||||
if ch == "{":
|
||||
return self._readObject()
|
||||
if ch == "[":
|
||||
return self._readArray()
|
||||
if ch == '"':
|
||||
return self._readString()
|
||||
if ch == "'":
|
||||
return self._readString("'")
|
||||
if ch == "t" or ch == "f":
|
||||
return self._readLiteral()
|
||||
if ch == "n":
|
||||
return self._readNull()
|
||||
return self._readNumber()
|
||||
|
||||
def _skipWhitespace(self):
|
||||
while self._index < len(self._source) and self._source[self._index] in " \t\n\r":
|
||||
self._index += 1
|
||||
|
||||
def _readObject(self):
|
||||
self._index += 1 # skip {
|
||||
obj = JSONObject()
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == "}":
|
||||
self._index += 1
|
||||
return obj
|
||||
while True:
|
||||
self._skipWhitespace()
|
||||
key = self.nextValue()
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == ":":
|
||||
self._index += 1
|
||||
self._skipWhitespace()
|
||||
val = self.nextValue()
|
||||
obj.put(str(key), val)
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == ",":
|
||||
self._index += 1
|
||||
elif self._index < len(self._source) and self._source[self._index] == "}":
|
||||
self._index += 1
|
||||
return obj
|
||||
else:
|
||||
raise JSONException("Expected ',' or '}' in object")
|
||||
|
||||
def _readArray(self):
|
||||
self._index += 1 # skip [
|
||||
arr = JSONArray()
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == "]":
|
||||
self._index += 1
|
||||
return arr
|
||||
while True:
|
||||
self._skipWhitespace()
|
||||
val = self.nextValue()
|
||||
arr.put(val)
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == ",":
|
||||
self._index += 1
|
||||
elif self._index < len(self._source) and self._source[self._index] == "]":
|
||||
self._index += 1
|
||||
return arr
|
||||
else:
|
||||
raise JSONException("Expected ',' or ']' in array")
|
||||
|
||||
def _readString(self, quote='"'):
|
||||
self._index += 1 # skip quote
|
||||
result = []
|
||||
while self._index < len(self._source):
|
||||
ch = self._source[self._index]
|
||||
if ch == "\\":
|
||||
self._index += 1
|
||||
if self._index >= len(self._source):
|
||||
raise JSONException("Unterminated string escape")
|
||||
esc = self._source[self._index]
|
||||
if esc == '"':
|
||||
result.append('"')
|
||||
elif esc == "\\":
|
||||
result.append("\\")
|
||||
elif esc == "/":
|
||||
result.append("/")
|
||||
elif esc == "b":
|
||||
result.append("\b")
|
||||
elif esc == "f":
|
||||
result.append("\f")
|
||||
elif esc == "n":
|
||||
result.append("\n")
|
||||
elif esc == "r":
|
||||
result.append("\r")
|
||||
elif esc == "t":
|
||||
result.append("\t")
|
||||
elif esc == "u":
|
||||
hex_str = self._source[self._index+1:self._index+5]
|
||||
result.append(chr(int(hex_str, 16)))
|
||||
self._index += 4
|
||||
else:
|
||||
result.append(esc)
|
||||
self._index += 1
|
||||
elif ch == quote:
|
||||
self._index += 1
|
||||
return "".join(result)
|
||||
else:
|
||||
result.append(ch)
|
||||
self._index += 1
|
||||
raise JSONException("Unterminated string")
|
||||
|
||||
def _readLiteral(self):
|
||||
for lit in ("true", "false"):
|
||||
if self._source[self._index:self._index+len(lit)] == lit:
|
||||
self._index += len(lit)
|
||||
return lit == "true"
|
||||
raise JSONException(f"Unexpected literal at {self._index}")
|
||||
|
||||
def _readNull(self):
|
||||
if self._source[self._index:self._index+4] == "null":
|
||||
self._index += 4
|
||||
return JSONObject.NULL
|
||||
raise JSONException(f"Unexpected token at {self._index}")
|
||||
|
||||
def _readNumber(self):
|
||||
start = self._index
|
||||
while self._index < len(self._source) and self._source[self._index] in "-+0123456789.eE":
|
||||
self._index += 1
|
||||
num_str = self._source[start:self._index]
|
||||
if "." in num_str or "e" in num_str or "E" in num_str:
|
||||
return float(num_str)
|
||||
return int(num_str)
|
||||
|
||||
def nextString(self, quote='"'):
|
||||
return self._readString(quote)
|
||||
|
||||
def nextChar(self, c):
|
||||
self._skipWhitespace()
|
||||
if self._index < len(self._source) and self._source[self._index] == c:
|
||||
self._index += 1
|
||||
return c
|
||||
raise JSONException(f"Expected '{c}'")
|
||||
|
||||
def nextTo(self, delimiter):
|
||||
start = self._index
|
||||
while self._index < len(self._source) and self._source[self._index] not in delimiter:
|
||||
self._index += 1
|
||||
return self._source[start:self._index]
|
||||
|
||||
def skipPast(self, text):
|
||||
idx = self._source.find(text, self._index)
|
||||
if idx >= 0:
|
||||
self._index = idx + len(text)
|
||||
|
||||
def skipTo(self, c):
|
||||
idx = self._source.find(c, self._index)
|
||||
if idx >= 0:
|
||||
self._index = idx
|
||||
return idx
|
||||
return -1
|
||||
|
||||
def back(self):
|
||||
self._index -= 1
|
||||
|
||||
def more(self):
|
||||
self._skipWhitespace()
|
||||
return self._index < len(self._source)
|
||||
|
||||
def readString(self):
|
||||
return self._readString()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONWriter
|
||||
# ============================================================
|
||||
|
||||
class JSONWriter(Stub):
|
||||
def __init__(self, writer):
|
||||
super().__init__()
|
||||
self._writer = writer
|
||||
self._stack = []
|
||||
self._in_object = False
|
||||
self._need_comma = False
|
||||
|
||||
def _write(self, s):
|
||||
self._writer.write(s)
|
||||
|
||||
def array(self):
|
||||
self._beforeValue()
|
||||
self._stack.append(("array", False))
|
||||
self._write("[")
|
||||
return self
|
||||
|
||||
def endArray(self):
|
||||
self._write("]")
|
||||
self._stack.pop()
|
||||
return self
|
||||
|
||||
def object(self):
|
||||
self._beforeValue()
|
||||
self._stack.append(("object", False))
|
||||
self._write("{")
|
||||
return self
|
||||
|
||||
def endObject(self):
|
||||
self._write("}")
|
||||
self._stack.pop()
|
||||
return self
|
||||
|
||||
def key(self, s):
|
||||
if not self._stack or self._stack[-1][0] != "object":
|
||||
raise JSONException("Can't set key outside object")
|
||||
self._beforeKey()
|
||||
self._write('"' + s + '":')
|
||||
return self
|
||||
|
||||
def value(self, v):
|
||||
self._beforeValue()
|
||||
self._write(JSONObject._value_to_string(v))
|
||||
return self
|
||||
|
||||
def _beforeValue(self):
|
||||
if self._stack and self._stack[-1][0] == "object":
|
||||
raise JSONException("Expected key in object")
|
||||
|
||||
def _beforeKey(self):
|
||||
if self._stack and self._stack[-1][1]:
|
||||
self._write(",")
|
||||
self._stack[-1] = (self._stack[-1][0], True)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONStringer
|
||||
# ============================================================
|
||||
|
||||
class JSONStringer(JSONWriter):
|
||||
def __init__(self):
|
||||
from io import StringIO
|
||||
super().__init__(StringIO())
|
||||
|
||||
def toString(self):
|
||||
return self._writer.getvalue()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONPointer
|
||||
# ============================================================
|
||||
|
||||
class JSONPointer(Stub):
|
||||
def __init__(self, pointer):
|
||||
super().__init__()
|
||||
if not pointer or pointer == "":
|
||||
self._tokens = []
|
||||
elif pointer.startswith("#"):
|
||||
pointer = pointer[1:]
|
||||
pointer = pointer.replace("~1", "/").replace("~0", "~")
|
||||
import urllib.parse
|
||||
pointer = urllib.parse.unquote(pointer)
|
||||
self._tokens = pointer.split("/")[1:] if len(pointer) > 1 else []
|
||||
else:
|
||||
self._tokens = pointer.split("/")[1:] if len(pointer) > 0 else []
|
||||
|
||||
def query(self, root):
|
||||
current = root
|
||||
for token in self._tokens:
|
||||
token = token.replace("~1", "/").replace("~0", "~")
|
||||
if isinstance(current, JSONObject):
|
||||
current = current.get(token)
|
||||
elif isinstance(current, JSONArray):
|
||||
try:
|
||||
idx = int(token)
|
||||
current = current.get(idx)
|
||||
except (ValueError, IndexError):
|
||||
raise JSONException(f"Invalid index: {token}")
|
||||
else:
|
||||
raise JSONException(f"Cannot index into {type(current)}")
|
||||
return current
|
||||
|
||||
def queryFrom(self, root):
|
||||
return self.query(root)
|
||||
|
||||
def toString(self):
|
||||
return "#/" + "/".join(t.replace("~", "~0").replace("/", "~1") for t in self._tokens)
|
||||
|
||||
def hashCode(self):
|
||||
return hash(tuple(self._tokens))
|
||||
|
||||
def equals(self, other):
|
||||
if isinstance(other, JSONPointer):
|
||||
return self._tokens == other._tokens
|
||||
return False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JSONPointerBuilder
|
||||
# ============================================================
|
||||
|
||||
class JSONPointerBuilder(Stub):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tokens = []
|
||||
|
||||
def append(self, token):
|
||||
self._tokens.append(str(token))
|
||||
return self
|
||||
|
||||
def build(self):
|
||||
return JSONPointer("#/" + "/".join(t.replace("~", "~0").replace("/", "~1") for t in self._tokens))
|
||||
Reference in new issue
Block a user