Базовое использование Simple мы рассмотрели, но есть одна особенность, которую хочется разобрать отдельно.
Иногда просто аннотаций бывает недостаточно. Бывает, что в объектной модели есть поля таких типов, к которым мы либо не можем написать маппинги, либо там нужна более сложная логика, чем просто отображение узлов и атрибутов. Обычный пример — любые классы для работы с датами: что стандартный Calendar
, что более приятный DateTime
из библиотеки joda-time. Дата в XML может представляться миллисекундами, секундами, отформатированной строкой и чем угодно ещё. Задать правила разбора не всегда предоставляется возможным.
В Simple подобные задачи предусмотрены, и для них существует концепция Matcher-ов.
Для примера возьмем обычный rss с какими-нибудь новостями. В новости есть поле pubDate
, в котором обычно строка вида Tue, 29 Oct 2013 14:52:57 +0400
. Нам хорошо бы получить из неё поле типа Calendar
.
Порядок действий следующий:
Transform
Для начала определяем наследника класса Transform<T>
, который отвечает за преобразование типа из строки и в строку:
public class CalendarTransform implements Transform<Calendar> { final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyy HH:mm:ss zzz", Locale.ENGLISH); @Override public Calendar read(String s) throws Exception { Calendar c = Calendar.getInstance(); c.setTime(dateFormat.parse(s)); return c; } @Override public String write(Calendar dateTime) throws Exception { return dateFormat.format(dateTime.getTime()); } }
Как несложно догадаться, write
будет использоваться для сериализации объекта, а read
— для десериализации.
Matcher
Matcher
нужен для того, чтобы было, где описать, какому классу соответствует какая трансформация. У нас особый случай всего один, так что код будет такой:
Matcher matcher = new Matcher() { @Override public Transform match(Class aClass) throws Exception { if (aClass == Calendar.class) { return new CalendarTransform(); } return null; } };
Вообще-то идея сопоставлять только по классу мне не очень нравится, потому что полей одного типа с разными форматами может быть несколько. В том же RSS для подкастов есть элемент Duration, который хорошо бы разбирать, как число и хранить там длительность в минутах. Но прогонять все другие возможные целочисленные поля в Matcher-е тип Integer
кажется не очень хорошей идеей. Но других возможностей у нас нет.
Serializer
Осталось подключить всю эту логику сериализатору:
Serializer serializer = new Persister(matcher);
Вот и всё. Теперь, когда сериализатор будет встречать поле класса Calendar
, оно будет разбираться именно в таком формате.
Best Casino for real money in New Jersey - Dr. Maryland
ОтветитьУдалитьFind the best casino 청주 출장샵 for you, 천안 출장안마 from slots and roulette 의왕 출장마사지 to blackjack. Start with a welcome bonus offer and 경기도 출장안마 start playing at the 여주 출장마사지 top of our