amarao (amarao_san) wrote,
amarao
amarao_san

json4shell

Спасибо No Way с 2ch'а, я чуть не выкинул jsonstream, хотя это то, что мне нужно.

Он даже умеет стекированный json (это когда один json сразу после другого).

Осталось две проблемы: обработка невалидного json'а (я отложу это чуть на потом)... Пока что идея простая - мы будем обворачивать входной поток в "резервную" скобку, так что обрывок json'а покажется массивом. Или объектом? Надо думать. Список интереснее.

Вторая проблема: как понять, что из надёрганных из потока пар пока делать итерацию? Основная проблема состоит в том, в каком формате yield'дятся значения.

Выглядит это так:

[
    {"a1":"11","a2":"12","a3":"13" },
    {"a1":"21","a2":"22","a3":"23" },
    {"a1":"31","a2":"32","a3":"33" }
]


Нам выдают значения в следующем виде:
((), [])
((0,), {})
((0, u'a1'), u'11')
((0, u'a2'), u'12')
((0, u'a3'), u'13')
((1,), {})
((1, u'a1'), u'21')
((1, u'a2'), u'22')
((1, u'a3'), u'23')
((2,), {})
((2, u'a1'), u'31')
((2, u'a2'), u'32')
((2, u'a3'), u'33')

То есть нет "закрывающего тега". Мы можем заняться синтетикой и имитировать наличие закрывающего тега по одному из двух признаков:

1. анонсирован объект того же уровня глубины или выше, как и наш. Поскольку сам анонс нам ни холодно ни жарко, то мы его можем "съесть"... Хотя при этом, наверное, assemble не сработает. В любом случае, можно написать буфферизованный врапер-итератор над потоком, куда можно "развидеть" элемент.
2. Мы получили StopIteration

Оба хорошо ложатся на модель "итератор с реверсивным ходом и буфером".

ТО есть схема такая:

На входе у нас поток анонсов от JSONStream. Специальный хитропопый итератор, принимает на вход такой простой итератор. Но yield'ит он только "готовый субоъект", то есть, например, словарь как элемент списка". Когда yield'ить он знает, если вычитал лишку, кладёт в свой буфер.

То есть (опуская детали):

def buff_iter(j_iter):
    buf=[]
    while пока_не_хватит:
        n=j_iter.next()
        if n == обычный объект:
            buf.append(n)
        elif n == новый_объект_или_конец:
            yield assemble(buf)
            buf= list(n)


Где-то тут будет ещё обработка внешних вложенностей, хотя я прихожу к мысли, что если приспичит, то выковырять с помощью jq или соответствующей специальной программы, а наш json-iterate должен работать с входным списком или стекированным json'ом. Надо ли работать с dict'ом я даже и не знаю. В принципе, если игнорировать существование ключей, то можно и пофигу...

UPD: нашаманил, очень грубо, вот такое:

На вход получает либо массив объектов, либо стопку объектов, на выходе - питоновские объекты для итерирования. Вложенные словари/объекты пока не делал, меня больше идея интересует.

https://github.com/amarao/json4shell/tree/jsonstream/tools

./run sample_data для результатов.
Tags: json4shell
Subscribe

  • ансибло-философия

    А вот я хочу продолжить думать умное про ансибл, ci/cd и прочую рабочую фигню между гитом и сервером. Классическое программирование стремится…

  • positive nagging

    Для повышения морали в коллективе было решено запретить токсичные и негативные сообщения в чате. Теперь все сообщения в чате выглядят так: Resolved…

  • Шли годы, а я учусь башу.

    Офигеть. Офигеть. echo <(echo hello) foobar /dev/fd/63 foobar Я этого честно не знал. Я знал, что в конце можно, а что можно в середине -…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments