def read_number(reader, ch): u"""用于读取数字内容,ch表示上一个被读取到的字符""" num_str = ch isfloat = False while reader.has_next(): ch = reader.get_next() if ch.isspace(): break # 读取到逗号,冒号或结束符('}', ']')需要回退一个位置,交给后面的方法处理 elif ch in (',', ':', '}', ']'): reader.get_prev() break elif ch in ('e', '.'): isfloat = True num_str += ch elif ch.isdigit() or ch == '-': num_str += ch else: raise JsonFormatError("Invalid char when read number : %s" % ch) # 根据标记位进行对应转换 try: if isfloat: return float(num_str) else: return int(num_str) except ValueError: log.warning("Json num format error, string:%s", string) raise JsonFormatError("Invalid num format, num string:%s" % string)
def _process_escape_char(reader, next_ch): u"""用于处理,并返回一个合法转义字符""" if next_ch == '"': escape_char = '"' elif next_ch == '\'': escape_char = '\'' elif next_ch == 'n': escape_char = '\n' elif next_ch == 't': escape_char = '\t' elif next_ch == 'r': escape_char = '\r' elif next_ch == 'b': escape_char = '\b' elif next_ch == 'f': escape_char = '\f' elif next_ch == '\\': escape_char = '\\' elif next_ch == 'u': # 处理Unicode编码 unicode_char = '\u' for i in range(4): ch = reader.get_next() if ch not in hexdigits: raise JsonFormatError("Invalid hex char : %s" % ch) unicode_char += ch escape_char = unicode_char.decode("raw_unicode_escape") else: raise JsonFormatError("Invalid escape char : %s" % next_ch) return escape_char
def read_array(reader): json_array = [] while reader.has_next(): ch = reader.get_next() if ch.isspace(): continue if ch == ']': break # 前移一位,在read_value中获取值 reader.get_prev() json_array.append(read_value(reader)) # 读取下一个非空字符,判断是否 , 或者 ] non_space_char = read_non_space_char(reader) if non_space_char == ']': break elif non_space_char == ',': continue else: log.warning("Char after array value must be ',' or ']', ch:%s", ch) raise JsonFormatError( "Next char after array value must be ',' or ']', ch:%s" % ch) else: log.warning("Invalid json array format, lost ']'") raise JsonFormatError("Json array lost ']'") return json_array
def read_object(reader): json_obj = {} while reader.has_next(): ch = reader.get_next() if ch.isspace(): continue elif ch == '}': break # 按照 key , : , value顺序读取数据 key = read_key(reader, ch) ch = read_non_space_char(reader) if ch != ":": raise JsonFormatError("After key must be colon ':'") value = read_value(reader) # 忽略非字符串类型的key if not isinstance(key, (str, unicode)): log.info("Key must be str, key:%s, ignore it.", key) else: json_obj[key] = value # 读取下一个非空字符,判断是否 , 或者 } non_space_char = read_non_space_char(reader) if non_space_char == '}': break elif non_space_char == ',': continue else: log.warning("Char after value must be ',' or '}'") raise JsonFormatError( "Char after value must be ',' or '}', ch:%s" % ch) else: log.warning("Invalid json obj format, lost '}'") raise JsonFormatError("Json obj lost '}'") return json_obj
def read_identifier(reader, identifier_chars, ret_val): u""" 读取Json中的标识符,比如:null,则传入:('u', 'l', 'l'), None 头一个字符可以忽略,因为头个字符在判断时已经被读取 :param reader: :param identifier_chars: :param ret_val: :return: """ length = len(identifier_chars) for i in range(length): ch = reader.get_next() if ch is None or ch != identifier_chars[i]: raise JsonFormatError("Invalid identifier value when read %s" % str(ret_val)) else: return ret_val
def json_to_object(json): if not isinstance(json, (str, unicode)): log.debug("Argument type was not str, argument:%s", json) raise TypeError("Argument must be str type") json = json.strip() res_obj = None reader = StringReader(json) while reader.has_next(): ch = reader.get_next() if ch == '{': res_obj = read_object(reader) elif ch == '[': res_obj = read_array(reader) else: log.debug("Invalid json format, json string should start with " "start with '{' or '[', argument:%s", json) raise JsonFormatError("Json string must start with '{' or '['") return res_obj
def read_value(reader): while reader.has_next(): ch = reader.get_next() if ch.isspace(): continue elif ch == '"': return read_string(reader) elif ch == '-' or ch.isdigit(): return read_number(reader, ch) elif ch in ('i',): return read_inf(reader) elif ch in ('n',): return read_null(reader) elif ch in ('t',): return read_true(reader) elif ch in ('f',): return read_false(reader) elif ch == '{': return read_object(reader) elif ch == '[': return read_array(reader) else: raise JsonFormatError("Invalid value format, read char:%s" % ch)
def read_key(reader, ch): if ch == '"': return read_string(reader) else: log.warning("Key must be string type") raise JsonFormatError("Invalid key type")