Пример #1
0
 def parse(self, input_stream, alias_map=None, schema=None, append_to=None, buf_size=65536, \
           **kwargs):
     '''Потоковый разбор JSON'''
     assert input_stream, 'Не задан источник данных'
     #переменные которые будут переданы в callback
     self.kwargs = kwargs
     #словарь с деревом запроса для определения PK
     if schema != self.schema:
         self.schema = schema
         self.schema_map.clear()
         self._traverse_query_paths(schema)
     # map(краткое имя -> полное имя)
     assert alias_map is None or isinstance(
         alias_map, dict), 'Неверный тип справочника aliasов'
     self.alias_map = alias_map
     #наш герой - C Stream JSon Parser
     self.parser = YajlParser(self, buf_size)
     self.parser.allow_multiple_values = True
     self.parser.dont_validate_strings = True
     #инициализуем для повторного использования
     self.root = append_to if append_to is not None else None
     self.current = append_to if append_to is not None else None
     #парсим
     try:
         self.parser.parse(input_stream)
     except YajlParseCancelled as err:
         print(err)
         self.error = err
         return False
     except YajlError as err:
         print(err)
         self.error = err
         return False
     else:
         return True
Пример #2
0
def main():
    opt_parser = optparse.OptionParser(
        description='validate json from stdin',
        version='Yajl-Py for Yajl %s' %yajl_version)
    opt_parser.add_option("-q",
        action="store_false", dest="verbose", default=True,
        help="quiet mode")
    opt_parser.add_option("-c",
        dest="allow_comments", action="store_true", default=False,
        help="allow comments")
    opt_parser.add_option("-u",
        dest="dont_validate_strings", action='store_true', default=False,
        help="allow invalid utf8 inside strings")
    (options, args) = opt_parser.parse_args()
    yajl_parser = YajlParser()
    yajl_parser.allow_comments = options.allow_comments
    yajl_parser.dont_validate_strings = options.dont_validate_strings
    retval = 0
    try:
        yajl_parser.parse()
    except YajlError as e:
        retval = 1
        if options.verbose:
            sys.stderr.write(e.value.decode('utf-8'))
    if options.verbose:
        print("JSON is %s" %("invalid" if retval else "valid"))
    raise SystemExit(retval)
Пример #3
0
def get_path(json_stream):
    path_getter = ContentHandler()
    parser = YajlParser(path_getter)
    try:
        parser.parse(f=json_stream)
    except YajlError as e:
        if 'premature EOF' in e.value:
            pass
        else:
            return 'invalid json'
    return path_getter.get_path()
Пример #4
0
def parse_json_utf8_bytes(bytesio: io.BytesIO) -> ParseJsonResult:
    """
    Parse JSON text into a List of columns.

    * Return error text on invalid JSON ... plus all the data parsed up to the
      error. (Lots of JSON parse errors are "JSON was truncated"; in that case
      we want all the data.)
    * Parse str/int/float as-is; for the rest, concatenate JSON tokens as str.
    * Drop every row starting at MAX_BYTES_PER_TABLE (and warn)
    * Drop every column after MAX_COLUMNS_PER_TABLE (and warn)
    * Drop every row starting at MAX_ROWS_PER_TABLE (and warn)
    """
    content_handler = JsonContentHandler()  # holds our data
    parser = YajlParser(content_handler)
    errors = []
    try:
        parser.parse(bytesio)
    except (JsonRootIsNotArray, JsonRecordIsNotObject):
        errors.append(
            "Workbench cannot import this JSON file. The JSON file "
            "must be an Array of Objects for Workbench to import it.")
    except JsonNumberTooLarge as err:
        errors.append(
            f'Stopped parsing JSON because the number "{err.value_str}" '
            "is too large.")
    except JsonTooManyRows:
        errors.append("The input had too many rows, so we removed rows.")
    except JsonTooManyBytes:
        errors.append(
            "The input was too large, so we stopped before reading the whole "
            "file.")
    except YajlError as err:
        # e.g., 'lexical error: ...\n    blah\n    ^^here'
        multiline_err = str(err)
        oneline_err = multiline_err.split("\n")[0]
        if (content_handler.columns
                and next(iter(content_handler.columns.values())).values):
            errors.append("Stopped parsing after JSON " + oneline_err)
        else:
            errors.append("JSON " + oneline_err)

    if content_handler.truncated_columns:
        errors.append("The input had too many columns, so we removed some.")

    return ParseJsonResult(content_handler.columns, "\n".join(errors))
Пример #5
0
def main():
    opt_parser = optparse.OptionParser(
        description='reformat json from stdin',
        version='Yajl-Py for Yajl %s' % yajl_version)
    opt_parser.add_option("-m",
        dest="beautify", action="store_false", default=True,
        help="minimize json rather than beautify (default)")
    opt_parser.add_option("-u",
        dest="dont_validate_strings", action='store_true', default=False,
        help="allow invalid UTF8 inside strings during parsing")
    opt_parser.add_option("-e",
        dest="escape_solidus", action='store_true', default=False,
        help="escape any forward slashes (for embedding in HTML)")
    opt_parser.add_option("-s",
        dest="stream", action='store_true', default=False,
        help="reformat a stream of multiple json entites")
    (options, args) = opt_parser.parse_args()
    # initialize the content handler (creates a Yajl Gen)
    ch = ReformatContentHandler(
        beautify=options.beautify,
        stream=options.stream,
    )
    # initialize the parser
    yajl_parser = YajlParser(ch)
    yajl_parser.allow_comments = True  # let's allow comments by default
    yajl_parser.allow_multiple_values = True
    yajl_parser.dont_validate_strings = options.dont_validate_strings
    yajl_parser.allow_multiple_values = options.stream
    yajl_parser.parse()
Пример #6
0
def main(args):
    parser = YajlParser(ContentHandler())
    parser.allow_multiple_values = True
    if args:
        for fn in args:
            f = open(fn)
            parser.parse(f=f)
            f.close()
    else:
        parser.parse()
    return 0
Пример #7
0
    def parse(self):
	ret = None
        self.handler = ParseContentHandler(callbacks)
        self.parser = YajlParser(content_handler = self.handler)
	self.parser.dont_validate_strings = self.utf8
        fh = self.filename
	try:
            fh.read()
        except AttributeError:
            fh =  open(self.filename, 'r')

	try:
	    self.parser.parse(fh)
	except KillParse as e:
	    ret = e.ret
        if "FinalCallback" in self.callbacks:
            if "CallbackData" in self.callbacks:
                ret = self.callbacks["FinalCallback"](ret, self.callbacks)
            else:
                ret = self.callbacks["FinalCallback"](ret)
        fh.close()
	return ret
Пример #8
0
def main(args):
    parser = YajlParser(ContentHandler())
    parser.allow_multiple_values = True
    if args:
        for fn in args:
            f = open(fn)
            parser.parse(f=f)
            f.close()
    else:
        parser.parse()
    return 0
Пример #9
0
def main():
    opt_parser = optparse.OptionParser(description='reformat json from stdin',
                                       version='Yajl-Py for Yajl %s' %
                                       yajl_version)
    opt_parser.add_option("-m",
                          dest="beautify",
                          action="store_false",
                          default=True,
                          help="minimize json rather than beautify (default)")
    opt_parser.add_option(
        "-u",
        dest="dont_validate_strings",
        action='store_true',
        default=False,
        help="allow invalid UTF8 inside strings during parsing")
    opt_parser.add_option(
        "-e",
        dest="escape_solidus",
        action='store_true',
        default=False,
        help="escape any forward slashes (for embedding in HTML)")
    opt_parser.add_option("-s",
                          dest="stream",
                          action='store_true',
                          default=False,
                          help="reformat a stream of multiple json entites")
    (options, args) = opt_parser.parse_args()
    # initialize the content handler (creates a Yajl Gen)
    ch = ReformatContentHandler(
        beautify=options.beautify,
        stream=options.stream,
    )
    # initialize the parser
    yajl_parser = YajlParser(ch)
    yajl_parser.allow_comments = True  # let's allow comments by default
    yajl_parser.allow_multiple_values = True
    yajl_parser.dont_validate_strings = options.dont_validate_strings
    yajl_parser.allow_multiple_values = options.stream
    yajl_parser.parse()
Пример #10
0
class JsonParser(YajlContentHandler):
    '''
    Класс для сборки JSON-объекта из строки и вызова обработчика по подписке
    '''
    def __init__(self, callbacks=None, encoding='utf-8'):
        '''Инициализация объекта для сборки JSON'''
        if callbacks:
            assert isinstance(callbacks, dict), 'Неверный тип параметра'
        self.encoding = encoding
        #корень дерева
        self.root = None
        #текуший узел, по которому идет парсинг
        self.current = None
        self.path = None
        #обработчки по подписке
        self.callbacks = callbacks
        self.kwargs = None
        self.parser = None
        self.error = None
        #словарь для преобразования кратких имен в полные
        self.alias_map = None
        #переменные которые будут переданы в callback
        self.kwargs = None
        #словарь с деревом запроса для определения PK
        self.schema = None
        # кеш схемф (путь->сущность)
        self.schema_map = dict()
        self.encode = encodings.search_function(encoding).encode
        self.decode = encodings.search_function(encoding).decode

    def _push(self, value=None, key=None):
        '''Создание нового уровня иерархии в стеке'''
        _next = JsonTree(value, parent=self.current, key=key)
        self.current = _next
        if self.root is None:
            self.root = self.current

    def _pop(self):
        '''Извлечение готового элемента из стека'''
        value = self.current
        if self.current is not None:
            self.current = self.current.parent
        return value

    def _set_value(self, value):
        '''
        Устанавливает  значение для нескалярного типа
        Для структуры - значение для ключа
        Для массиса - добавляет очередное значение
        '''
        if self.current is None:
            #Чтобы не вставлять изначально пустой узел, подбираем первый обработанный узел
            # в качестве корня. Если присляли скаляр - создаем узел
            if isinstance(value, JsonTree):
                self.current = value
                if self.root is None:
                    self.root = value
                return
            else:
                self.current = JsonTree()
                if self.root is None:
                    self.root = self.current
        if self.current.type == JsonTree.t_dict:
            if self.current.key is None:
                #Если не задан ключ - объединяем структуры. Сделано для объединения
                #последовательности json в 1 большой
                if isinstance(value,
                              JsonTree) and value.type == JsonTree.t_dict:
                    self.current().update(value())
                    return
                if isinstance(value, JsonTree.t_dict):
                    self.current().update(value)
                    return
                else:
                    raise ValueError(
                        'Ошибка интерпретации структуры. На задан ключ для значения'
                    )

            self.current[self.current.key] = value
            self.current.key = None
        elif self.current.type == JsonTree.t_list:
            self.current().append(value)
        else:
            self.current.value = value

    def _callback_trigger(self, path, node):
        '''Вызов событий по подписке'''
        if self.callbacks:
            for trigger in self.callbacks:
                #                if isinstance(trigger, (list, tuple)):
                #                    trigger = '/'.join(trigger)
                #                else:
                #                    trigger = str(trigger)
                #                if isinstance(path, list):
                #                    path = '/'.join(path)

                _cmp = lambda x, y: x == y if y[:2] == './' else x.endswith(y)
                if _cmp(path.lower(), trigger.lower()):
                    #Верни True - если успешно обработал узел и мы его грохнем из обработки
                    #Иначе верни False
                    return self.callbacks[trigger](node, self, **self.kwargs)

        return False

    #события от синтаксического генератора
    def parse_start(self):
        '''Обработка события начала разбора'''
        #        self.root = None #JsonTree()
        #        self.current = None #self.root
        self.path = '.'

    def parse_buf(self):
        '''Обработка события окончания обработки буфера'''
        pass

    def parse_complete(self):
        '''Обработка события окончания логического разбора JSON'''
        pass

    def yajl_null(self, ctx):
        '''Обработка события обработки значения'''
        self._set_value(None)

    def yajl_boolean(self, ctx, boolVal):
        '''Обработка события обработки значения'''
        self._set_value(boolVal)

    def yajl_integer(self, ctx, integerVal):
        '''Обработка события обработки значения'''
        self._set_value(int(integerVal))

    def yajl_double(self, ctx, doubleVal):
        self._set_value(float(doubleVal))

    def yajl_number(self, ctx, stringVal):
        '''Обработка события обработки значения'''
        if stringVal.isdigit():
            self.yajl_integer(ctx, self.decode(stringVal)[0])
        else:
            self.yajl_double(ctx, self.decode(stringVal)[0])

    def yajl_string(self, ctx, stringVal):
        '''Обработка события обработки значения'''
        self._set_value(self.decode(stringVal)[0])

    def yajl_start_map(self, ctx):
        '''Обработка события начала структуры'''
        # обработка пути
        if self.current is not None and self.current.key:
            self.path += '/' + self.current.key

        self._push(JsonTree.t_dict())

    def _map_2key(self, key):
        if self.alias_map:
            val = self.alias_map.get(key, key)
            val = val.name.replace('.', '_') if hasattr(val,
                                                        'name') else str(val)
        else:
            val = key
        return val.lower()

    def yajl_map_key(self, ctx, stringVal):
        '''Обработка события ключ структуры'''
        self.current.key = self._map_2key(self.decode(stringVal)[0])

    def yajl_end_map(self, ctx):
        '''Обработка события окончания структуры'''
        value = self._pop()
        #восстановим у структуры key. В current после pop - родитель
        if self.current is not None:
            value.key = self.current.key

        #обработка пути
        path = self.path
        if self.path:
            pos = self.path.rfind('/')
            self.path = self.path[:pos] if pos > 0 else '.'
        #триггер
        if self._callback_trigger(path, value):
            value = None
            return
        else:
            self._set_value(value)

    def yajl_start_array(self, ctx):
        '''Обработка события начала массива'''
        # массив запоминает ключ родителя
        key = self.current.key if self.current is not None else None
        #Подставляем здесь ключ (PK) для индексирования
        pk = None
        if self.schema and key:
            path = (self.path + '/' + key).lower() if self.path else ''
            entity = self.schema_map.get(path, None)
            if not entity:
                self.schema_map[path] = entity = self.schema.query(path, None)
            pk = entity.PK[0] if getattr(entity, 'indexed', False) else None

        self._push(JsonTree.t_list(pk=pk), key=key)

    def yajl_end_array(self, ctx):
        '''Обработка события окончания массива'''
        if self.current.key:
            self.current.key += '[]'
        self._set_value(self._pop())

    @property
    def json(self):
        '''Возвращает результат разбора'''
        return self.root

    @staticmethod
    def rebuild_root(node):
        '''Строит дерево вверх и востанавливает ссылки. Возвращает копию'''
        current = node
        parent = current.parent
        while parent is not None:
            # обработка. Не портим списки, в словари засовываем ссылки на фейковые массивы.
            # их все равно перезапишут
            if parent.type == JsonTree.t_list:
                parent = JsonTree(JsonTree.t_list(parent().pk), parent.key,
                                  parent.parent)
                parent().append(current)
            if parent.type == JsonTree.t_dict and parent.key:
                parent[parent.key] = current
            current = parent
            parent = current.parent
        return current

    def _traverse_query_paths(self, enitity, path=None, name=None):
        '''Формирование кеша'''
        if not path:
            path = '.'

        name = name.lower() if name else enitity.name.lower()
        path += '/%s' % name
        self.schema_map[path] = enitity
        for ent in enitity.subnodes:
            self._traverse_query_paths(enitity.subnodes[ent],
                                       path=path,
                                       name=ent)


    def parse(self, input_stream, alias_map=None, schema=None, append_to=None, buf_size=65536, \
              **kwargs):
        '''Потоковый разбор JSON'''
        assert input_stream, 'Не задан источник данных'
        #переменные которые будут переданы в callback
        self.kwargs = kwargs
        #словарь с деревом запроса для определения PK
        if schema != self.schema:
            self.schema = schema
            self.schema_map.clear()
            self._traverse_query_paths(schema)
        # map(краткое имя -> полное имя)
        assert alias_map is None or isinstance(
            alias_map, dict), 'Неверный тип справочника aliasов'
        self.alias_map = alias_map
        #наш герой - C Stream JSon Parser
        self.parser = YajlParser(self, buf_size)
        self.parser.allow_multiple_values = True
        self.parser.dont_validate_strings = True
        #инициализуем для повторного использования
        self.root = append_to if append_to is not None else None
        self.current = append_to if append_to is not None else None
        #парсим
        try:
            self.parser.parse(input_stream)
        except YajlParseCancelled as err:
            print(err)
            self.error = err
            return False
        except YajlError as err:
            print(err)
            self.error = err
            return False
        else:
            return True
def parseToQueue(stream, queue, column_map):
    parser = YajlParser(ContentHandler(queue, column_map))
    parser.parse(stream)
    queue.put(None)
Пример #12
0
class ScarfJSONReader:
    def __init__(self, inputFile):
        self.callbacks = {}
        self.handler = None
        self.parser = None
        self.filename = inputFile
	self.utf8 = 1;

    #################Callback Accessors/Mutators##############
    def SetInitialCallback(self, callback):
        self.callback["InitialCallback"] = callback

    def SetBugCallback(self, callback):
        self.callback["BugCallback"] = callback

    def SetMetricCallback(self, callback):
        self.callback["MetricCallback"] = callback

    def SetBugSummaryCallback(self, callback):
        self.callback["BugSummaryCallback"] = callback

    def SetMetricSummaryCallback(self, callback):
        self.callback["MetricSummaryCallback"] = callback

    def SetFinalCallback(self, callback):
        self.callback["FinalCallback"] = callback

    def SetCallbackData(self, callbackData):
        self.callback["CallbackData"] = callback

    def SetUTF8(self, utf8):
	self.utf8 = utf8


    def GetUTF8(self):
	return self.utf8

    def GetInitialCallback(self):
        return self.callback["InitialCallback"]

    def GetBugCallback(self):
        return self.callback["BugCallback"]

    def GetMetricCallback(self):
        return self.callback["MetricCallback"]

    def GetBugSummaryCallback(self):
        return self.callback["BugSummaryCallback"]

    def GetMetricSummaryCallback(self):
        return self.callback["MetricSummaryCallback"]

    def GetFinalCallback(self):
        return self.callback["FinalCallback"]

    def GetCallbackData(self):
        return self.callback["CallbackData"]



    def parse(self):
	ret = None
        self.handler = ParseContentHandler(callbacks)
        self.parser = YajlParser(content_handler = self.handler)
	self.parser.dont_validate_strings = self.utf8
        fh = self.filename
	try:
            fh.read()
        except AttributeError:
            fh =  open(self.filename, 'r')

	try:
	    self.parser.parse(fh)
	except KillParse as e:
	    ret = e.ret
        if "FinalCallback" in self.callbacks:
            if "CallbackData" in self.callbacks:
                ret = self.callbacks["FinalCallback"](ret, self.callbacks)
            else:
                ret = self.callbacks["FinalCallback"](ret)
        fh.close()
	return ret
def parseToQueue(stream, queue, column_map):
    parser = YajlParser(ContentHandler(queue, column_map))
    parser.parse(stream)
    queue.put(None)