Juravskiy Vitaliy`s blog

Январь 4, 2011

 

Преобразование Java объектов в JSON

Существует большое количество реализаций библиотек для работы с форматом JSON. В процессе изучения исходных кодов нескольких библиотек, выяснилось, что способы преобразования в JSON и обратно могут быть разные. Для преобразование Java объекта в JSON формат, наиболее простой способ, это использование Java аннотации для полей класса и функции формирования JSON строки. Рассмотрим на примере:

package example.json; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(value=ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface JsonName { String id(); }

Аннотацией необходимо пометить поля класса, который должен быть преобразован в JSON формат, так же поля класса могут содержать ссылки на массивы, объектов поля которых тоже помечены аннотацией.
Например так:

package example.json.data; import example.json.JsonName; public class People { @JsonName(id="name") private String name; @JsonName(id="age") private Integer age; private Integer debugId; @JsonName(id="id") priavte Integer id; @JsonName{id="children"} private People [] children; /** * getters and setters */ }

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

package example.json; import java.lang.reflect.Field; public class JsonWriter { public String getJsonString(Object o) { return buildJson(o); } /** * Создает JSON строку на основе класса переданного в параметре о. Поля класса, которые должны участовать в процесседолжны быть помечены анотацией {@link JsonName}. * @param o объект поля которого помечены аннотацией {@link JsonName} * @return json string */ private String buildJson(Object o) { StringBuffer json = new StringBuffer(); json.append("{"); Field [] fs = o.getClass().getDeclaredFields(); for (int i = 0; i < fs.length; i++) { Field f = fs[i]; f.setAccessible(true); Object value = null; try { value = f.get(o); } catch (IllegalArgumentException e1) { e1.printStackTrace(); } catch (IllegalAccessException e1) { e1.printStackTrace(); } if(f.isAnnotationPresent(JsonName.class) && value != null) { json.append("\"") .append(f.getAnnotation(JsonName.class).id()) .append("\"") .append(":"); try { if(value instanceof String) { json.append("\"") .append(value.toString()) .append("\""); } else if(f.getType().isArray()) { json.append("["); Object[] ar = (Object[])value; for (int j = 0; j < ar.length; j++) { json.append(buildJson(ar[j])); if(j != ar.length - 1) json.append(","); } json.append("]"); } else { json.append(value.toString()); } if(i != fs.length - 1) json.append(","); } catch (IllegalArgumentException e) { e.printStackTrace(); } } } json.append("}"); return json.toString(); } }

Несложно заметить что для поиска полей, помеченных аннотациями используется механизм отражения (reflection).
Пример использования всего выше перечисленного:

People man = new People() .setId(1) .setName("Ivan") .setAge(26); man.setChildren(new People[] { new People().setId(2).setName("Alex").setAge(5) });

Результат будет следующим:

{"name":"Ivan","age":26,"id":1,"children":[{"name":"Alex","age":5,"id":2}]}

Преобразование обратно, уже не является такой простой задачей, которую можно решить "с ходу".


Juravskiy Vitaliy`s blog

Январь 2, 2011

 

Стандарт Web Sockets

Ура свершилось! Можно отправить в trash что то типа ajax reverse, ajax push, comet и тому подобное.
W3 консорциум выделил отдельный стандарт из HTML 5 это Web Sockets. Разработчики ПО оперативно отреагировали на стандарт, так как это действительно прорыв в развитии Web.
Браузеры которые поддерживают стандарт:

  • Google Chrome начиная с релиза 4.0.249.0
  • Apple Safari
  • В FireFox 4 запланировали поддержку стандарта
  • Opera начиная с релиза 10.70
  • В Microsoft не все так гладко, поддержку стандарта обещают в Internet Explorer 9.

Поддержка в серверных приложениях:

  • В Apache модуль pywebsocket от Google
  • В PHP расширение phpwebsocket
  • J2EE контейнеры:
    • Jetty 7.0
    • GlassFish 3.0
    • Caucho Resin 4.0.2

Собственно говоря, а в чем дело, ну стандарт, ну реализовали, а в чем дело? А дело все в том, что теперь реализовывать “общение” браузера (клиента) с сервером, стало более оперативным, теперь все упирается в скорость обмена между сервером и клиентом.

Событие сгенерированное на клиенте может быть легко передано, другим клиентам – участникам общего процесса взаимодействия, будь то приложения мгновенного обмена сообщениями, или другое программное обеспечение которое критично к скорости доставки данных между клиентами и сервером.

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

Заголовок в классическом HTTP протоколе - лишний объем служебной информации, который постоянно приходиться передавать с клиента на сервер и обратно. В случае же с Web sockets количество заголовков уменьшено и равно одному, когда клиент устанавливает соединение.

Рассмотри пример кода клиентской стороны на JavaScript:

if ("WebSocket" in window) { var ws = new WebSocket("ws://localhost/service"); ws.onopen = function() { ... Web Socket is connected. You can send data by send() method. ws.send("message to send"); .... }; ws.onmessage = function (evt) { var received_msg = evt.data; ... }; ws.onclose = function() { .... websocket is closed. }; } else { ... the browser doesn't support WebSocket, use timers and ajax or comet. }

Обсуждение  Web Socket протокола еще не завершено, и возможны изменения как в API так и в протоколе.

В дальнейшем планирую рассмотреть реализации стандарта для северной части, говорят у jetty 7 наиболее просто в использовании API. Так же думаю взять за пример статью Jetty WebSocket Server, которая ориентированна на Jetty 7.  Так же говорят, что в jetty 8 войдет библиотека jwebsocket, на сайте которой много примеров по ее использованию и применению стандарта.