Pull to refresh

JSON против XML и немного рефакторинга

Reading time6 min
Views2.9K

Введение


Работая в области создания RIA, рано или поздно приходится задумываться над выбором протоколов для передачи данных между сервером и его клиентами. Если раньше я безоговорочно использовал XML, то сейчас все чаще задумываюсь над тем, чтобы поменять свой приоритет в данном вопросе в пользу JSON. Выше я не ошибся, говоря о клиентах, все чаще для своего сервиса заказчики требуют мобильную версию и поэтому приходится думать о создании серверной инфраструктуры, способной поддерживать несколько клиентов (браузер и, допустим, приложение для iPhone) и их версий. Вроде бы по всем параметрам подходит XML, но тут возникают сомнения.

Сомнения


Последние пару лет с опаской замечаю повсеместное использование XML — да формат универсальный, но надо знать меру. Главный флаг XML — машинночитаемый и человекочитаемый формат хранения данных, замечу — легко читаемый. В литературе вы найдете упоминание о том, что XML — это иерархическая структура, предназначенная для хранения любых данных, визуально структура может быть представлена как дерево.

И тут возникает первое сомнение: а вот если взять небольшое дерево, узлов на двести и сохранить в виде XML, так ли будет просто его прочитать. Человеку без специального редактора с подстветкой уже практически нереально читать такие файлы (особенно, если они записаны в одну строчку без переносов и табуляций). С этим утверждением сложно не согласиться.

Таким образом, следует откинуть человекочитаемость формата как преимущество и рассматривать XML прежде всего как средство коммуникаций между сервисими, программами или платформами, этакое платформонезависимое средство общения систем.

Исходя из вышеобоснованной позиции, возникает второе сомнение. А не дорого ли? В данном случае оценивается процессорное время. В последнем проекте пришлось замерять производительность (можно сказать жёстко «профайлить») и, надо сказать, одним из самых узких мест оказалась сериализация объектов в XML и их реинкарнация из него. Можно предположить, что руки надо мыть чаще, но за почти месяц борьбы за чистоту рядов, — производительность хоть и поднялась, но не настолько, чтобы радовать коллектив разработчиков.

Последний из камней сомнений, самый легкий и, в тоже время, фундаментально непоправимый, связан с объемом передаваемых данных, то есть объемом генерируемого трафика. Пока клиентов было мало, этой проблемы как бы и не существовало. Однако, когда появился мобильный клиент к сервису и одновременно в систему устремились толпы корпоративщиков, объем генерируемого трафика ясно указал на избыточность XML (генерирование белого шума), как протокола для работы с клиентскими приложения (с их большой массой).

Можно сделать вывод, что сложность использования XML превышает сложность тех проблем, которые эта технология решает. Вы сами можете придумать массу доводов за и массу против, как, в том числе, это делают даже создатели XML [TB, TB2]. Но в пользу XML, хочу заметить следующее: использование его в качестве протокола для синхронизации серверов практически идеально, а средства автоматизации разработки позволяют расслабиться и получать удовольствие. Но проблема клиентского трафика заставила обратить внимание на формат представления данных JSON.

Альтернатива


Главным источником информации о JSON является официальный сайт [JSON], содержащий следующее определение: JSON (JavaScript Object Notation) — простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. С ходу отметая определение, которое ориентированно на продвижение JSON в массы, отметим, что формат является: текстовым, открытым, простым и неплохо документированным [JSONdoc].

На мой взгляд, удобность читаемости человеком формата JSON по сравнению с XML еще ниже. Для проверки этого утверждения выполните любой запрос к поисковому API twitter.com, например: search.twitter.com/search.json?q=golodnyj, и попробуйте интерпретировать результат без ознакомления с самим API. У вас возникнут сложности, как минимум из-за того, что JSON не передает семантику, а предназначен для представления содержания. Исходя из вышесказанного, JSON следует определять как текстовый, открытый, легкий протокол сопряжения клиент-серверных приложений, ориентированный на передачу объектов.

Переход на использование JSON действительно значительно (до 25-30%) сократил объем пользовательского трафика и позволил значительно снизить нагрузку на сетевую инфраструктуру сервиса. Однако, как вы понимаете, пришлось заменить генерирование и парсинг с XML на JSON. Казалось бы, ничего хорошего в этом нет — значительный рефакторинг кода, отладка и длительное тестирование, но нам повезло.

Герой дня


Спасителем человечества в отдельно взятых его областях стал фреймфорк XStream [XS], который, по счастливому стечению обстоятельств, использовался для работы с XML именно в той части системы, над которой проводился эксперимент.

В качестве примера рассмотрим класс Client (полный исходный код смотрите в приложении 1), который имеет три атрибута, конструктор, геттеры и сеттеры:

package ru.golodnyj.lection.json;

public class Client {
  private String userName;
  private boolean verified;
  private int userId;

  public Client(String userName, boolean verified, int userId) {
    this.userName = userName;
    this.verified = verified;
    this.userId = userId;
  }
...
}


* This source code was highlighted with Source Code Highlighter.

А также класс ConsoleJSON (приложение 2), в котором сначала демонстрируется сериализация экземпляра класса Client в формат XML, а потом в JSON:

package ru.golodnyj.lection.json;
...

public class ConsoleJSON {
  public static void main(String[] args) {
    Client c = new Client("name",true , 5);

    // Создание XML
    XStream xstream = new XStream(new DomDriver());
    String xml = xstream.toXML(c );
    System.out.println("xml "+ xml.length() +" : \n" + xml);
    
    // Создание JSON
    XStream xstream1 = new XStream(new JsonHierarchicalStreamDriver());
    String json = xstream1.toXML(c );
    System.out.println("json "+ json.length() +" : \n" + json);
  }
}


* This source code was highlighted with Source Code Highlighter.

После запуска программы вы получите сообщение в консоле вида:

xml 145 :
<ru.golodnyj.lection.json.Client>
 <userName>name</userName>
 <verified>true</verified>
 <userId>5</userId>
</ru.golodnyj.lection.json.Client>
json 96 :
{"ru.golodnyj.lection.json.Client": {
 "userName": "name",
 "verified": true,
 "userId": 5
}}


* This source code was highlighted with Source Code Highlighter.

Сначала идет отображение XML — объем получившейся строки 145 символов, а затем JSON длинной 96 символом. Разница в длине строк при сериализации такого простого объекта значительная, что же говорить о сложных конструкциях. Конечно вывод для XML и для JSON можно сделать компактным, например, для передачи данных совершенно неважно полное каноническое имя класса и форматированный вывод.

Для улучшения вывода можно воспользоваться механизмом алиасов в XStream, который позволяет сопоставить с именем класса некоторую строковую переменную. А также, для формата JSON необходимо изменить драйвер с JsonHierarchicalStreamDriver(), обеспечивающий форматированный вывод, на JettisonMappedXmlDriver(), предназначенный для поточного вывода.

XStream xstream1 = new XStream(new JettisonMappedXmlDriver());
xstream1.alias(«client», Client.class);


* This source code was highlighted with Source Code Highlighter.

В таком случае JSON вариант для экземпляра объекта Client будет длинной 57 символов и выглядеть следующим образом:

{"client":{"userName":"name","verified":true,"userId":5}}

Процесс десериализации из XML в POJO также прост и заключается в вызове метода fromXML() экземпляра класса XStream, в качестве параметра которому передана JSON-строка, с последующим приведением типов данных.

Выводы


Если вы еще раз обратите внимание на класс ConsoleJSON, вы заметите как мало требуется для того, чтобы заменить вывод с XML на JSON. В результате имеем значительную экономию объема генерируемого трафика. В данном конкретном случае с серверной стороны процесс рефакторинга, имевший целью замену протокола передачи данных с XML на JSON, был очень простым и не потребовал значительных усилий.

ЛИТЕРАТУРА


[TB] Tim Bray www.tbray.org/ongoing/When/200x/2003/03/16/XML-Prog
[TB2] Tim Bray www.tbray.org/ongoing/When/200x/2003/03/24/XMLisOK
[JSON] www.json.org
[JSONdoc] www.json.org/json-ru.html
[XS] xstream.codehaus.org

Приложения


Приложение 1 dumpz.org/12012
Приложение 2 dumpz.org/12013
Tags:
Hubs:
Total votes 31: ↑29 and ↓2+27
Comments51

Articles