Подтвердить что ты не робот

Дельта-кодирование для объектов JSON

Существует ли стандартная библиотека или инструмент для вычисления и применения различий в документах JSON? В основном у меня есть куча довольно больших документов, которые я хочу синхронизировать по сети, и я бы предпочел не пересылать все свое состояние каждый раз, когда я хочу их синхронизировать (поскольку многие из этих переменных не будут меняться). Другими словами, я хочу только передать поля, которые изменились, а не ретранслировать весь объект. Я бы подумал, что было бы удобно иметь что-то вроде следующего набора методов:

//Start with two distinct objects on the server
// prev represents a copy of the state of the object on the client
// next represents a copy of the state of the object on the server
//
//1. Compute a patch
patch = computePatch(prev, next);

//2. Send patch over the network

//3. Apply the patch on the client
applyPatch(prev, patch);

//Final invariant:
//   prev represents an equivalent object to JSON.parse(JSON.stringify(next))

Я мог бы, конечно, реализовать его сам, но есть немало краевых случаев, которые нужно учитывать. Вот некоторые из простых (хотя и несколько неудовлетворительных) методов, о которых я могу думать, например:

  • Скачайте мой собственный патч JSON. Асимптотически это, вероятно, лучший способ, так как было бы возможно поддерживать все соответствующие функции документов JSON, а также поддерживать некоторые специализированные методы для создания таких вещей, как разные ints, doubleles и strings (с использованием относительного расстояния кодирования/редактирования), Однако у JSON много особых случаев, и я немного стараюсь сделать это без большого тестирования, и поэтому я бы предпочел найти то, что уже решает эту проблему для меня, чтобы я мог доверять ей, и не нужно беспокоиться о том, что сеть Heisenbugs появляется из-за ошибок в моем патче JSON

  • Просто вычислите расстояние редактирования непосредственно между строками JSON, используя динамическое программирование. К сожалению, это не сработает, если у клиента и сервера есть разные реализации JSON (т.е. Порядок их полей может быть сериализован по-разному), а также довольно дорого - это квадратичная операция времени.

  • Использовать буферы протокола. У буферов протокола есть встроенный метод diff, который делает именно то, что я хочу, и они являются красивым бинарным сериализуемым сетевым форматом. К сожалению, поскольку они также строго типизированы, им не хватает многих преимуществ использования JSON, таких как возможность динамического добавления и удаления полей. Сейчас это подход, к которому я сейчас склоняюсь, но это может сделать будущее обслуживание действительно ужасным, поскольку мне нужно будет постоянно обновлять каждый из моих объектов.

  • Сделайте что-нибудь действительно противное, например, создайте собственный протокол для каждого типа объектов и надейтесь, что я получу его в обоих местах (да, правильно!).

Конечно, я на самом деле надеюсь, что кто-то здесь, в stackoverflow, должен пройти и сохранить день со ссылкой на объект javascript с разным пространством, отличающийся /patcher, который был хорошо протестирован в производственных средах и в разных браузерах.

* Update *

Я начал писать свой собственный патчер, ранняя версия его доступна в github здесь:

https://github.com/mikolalysenko/patcher.js

Думаю, поскольку здесь, похоже, не так много, я вместо этого буду принимать в качестве альтернативного ответа список интересных тестовых примеров для патчера JSON.

4b9b3361

Ответ 1

Я занимаюсь библиотекой json diff и patch в github (да, бесстыдной плагин):

https://github.com/benjamine/JsonDiffPatch

он обрабатывает длинные строки автоматически, используя Neil Fraser diff_match_patch lib. он работает как на браузерах, так и на сервере (модульные тесты работают на обоих env). (полный список функций находится на странице проекта)

Единственное, что вам, возможно, понадобится, что не реализовано, - это возможность вводить пользовательские функции diff/patch для определенных объектов, но это не сложно добавить, вы можете их разблокировать и даже лучше отправить запрос на растяжение.

Привет,

Ответ 2

Я столкнулся с этим вопросом, ища реализации json-patch. Если вы катаетесь самостоятельно, вы можете захотеть основать его на этом проекте.

http://tools.ietf.org/html/draft-pbryan-json-patch-00

Ответ 4

Прежде чем вы начнете писать свои собственные утилиты для разграничения и исправления JSON с нуля, я бы предложил использовать существующие утилиты diff и patch для простого текста. Все, что вам действительно нужно сделать, это написать некоторую логику, которая принимает произвольную строку JSON и отображает в "канонической" форме JSON - так что любые две строки JSON, которые представляют эквивалентные данные, имеют "канонические" формы, которые идентичны текстовым строкам, а затем вы может использовать простой старый "патч", чтобы вычислить все ваши дельта для вас.

Кажется, что идея canonical JSON не нова, но код, необходимый для генерации канонического представления для произвольной строки JSON, не выглядит тривиальным, и похоже, что есть место для улучшения всего, что дядя Google показывает мне для" канонического JSON "прямо сейчас (включая ответы на этот вопрос, хотя используя Bencode, поскольку формат нормализации звучит многообещающе).

Это отличная новость, потому что это означает, что вы можете написать что-то новое и полезное! Держите нас в курсе, когда вы найдете работоспособное решение (я также хотел бы иметь возможность генерировать дельта JSON).

EDIT: подумав об этом, я понимаю, что идея "канонизации" вообще не помогает, так как одна и та же дельта-патч вообще не может применяться двумя текстовыми разными блоками JSON если они имеют одну и ту же "каноническую форму". Что вызывает вопрос: если вы просто отправляете "дельта" для документа JSON через провод, то почему бы просто не послать их как литеральные выражения (или, возможно, MIME с текстом типа /x -diff)? Чтобы защитить от коррупции из-за отброшенных патчей, вы можете захотеть добавить поле номера последовательности/ревизии где-нибудь (как в файл данных, так и в diff), или вы можете стать амбициозными и использовать протокол Delta-V (разработан для WebDAV). Может быть, вы уже это делаете? На этой неделе я попытаюсь посмотреть ваш код.

Ответ 5

Используйте JSON Patch, который стандартный способ сделать это.

Библиотеки существуют на многих платформах

Во время записи поддерживаются Javascript, Python, PHP, Ruby, Perl, C, Java, С#, Go, Haskell и Erlang (full список здесь).

Патч JSON - это формат для описания изменений в Документ JSON. Его можно использовать, чтобы избежать отправки целого документа, когда только часть изменилась. При использовании в сочетании с HTTP PATCH метод позволяет частично обновлять API-интерфейсы HTTP в стандартах совместимый способ.

Патч-документы сами являются документами JSON.

Патч JSON указан в RFC 6902 из IETF.