Иногда возникает задача преобразовать существующий XML-документ в эквивалентное ему JSON-представление. Например, такая задача может возникнуть, если вы разрабатываете AJAX-интерфейс к существующей системе, которая генерирует XML. Дело в том, что из JavaScript гораздо проще оперировать объектами, представленными в формате JSON, нежели XML, просто потому что первый формат - нативный.
Так вот, быстро преобразовать XML в JSON можно с помощью замечательной библиотеки XStream, подробное введение в которую опубликовано в статье xstream - сериализуем Java-класс в XML. В состав данной библиотеки входит драйвер JettisonMappedXmlDriver, отвечающий за быстрое преобразование XML -> JSON. Порядок преобразования следующий:
1. Создаем объект класса, реализующего интерфейс HierarchicalStreamReader, способный читать XML. Самой быстрой реализацией является класс XppReader.
2. Создаем объект класса JettisonMappedXmlDriver, кстати, данный класс реализует интерфейс HierarchicalStreamWriter.
3. С помощью метода HierarchicalStreamCopier#copy копируем данные из reader во writer.
Java-кодом этот несложный алгоритм записывается так:
import java.io.StringReader;
import java.io.StringWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.xml.XppReader;
public class Test
{
public static void main(String[] args)
{
String xml = "<user>" +
"<name>Pavel</name>" +
"<sername>Samolisov</sername>" +
"<age>23</age>" +
"<rating>89.93</rating>" +
"</user>";
StringWriter buffer = new StringWriter();
HierarchicalStreamReader reader = new XppReader(new StringReader(xml));
HierarchicalStreamWriter writer = new JettisonMappedXmlDriver().createWriter(buffer);
HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
copier.copy(reader, writer);
System.out.println(buffer);
}
}
import java.io.StringWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.xml.XppReader;
public class Test
{
public static void main(String[] args)
{
String xml = "<user>" +
"<name>Pavel</name>" +
"<sername>Samolisov</sername>" +
"<age>23</age>" +
"<rating>89.93</rating>" +
"</user>";
StringWriter buffer = new StringWriter();
HierarchicalStreamReader reader = new XppReader(new StringReader(xml));
HierarchicalStreamWriter writer = new JettisonMappedXmlDriver().createWriter(buffer);
HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
copier.copy(reader, writer);
System.out.println(buffer);
}
}
Для запуска примера потребуются следующие библиотеки, входящие в дистрибутив XStream:
jettison
stax-api
xpp3_min
xstream
В результате будет сгенерирована следующая строка в формате JSON:
{"user":{"name":"Pavel","sername":"Samolisov","age":"23","rating":"89.93"}}
Желающие могут померить производительность данной схемы, думаю она будет достаточной для большинства бизнес-приложений.
Понравилось сообщение - подпишитесь на блог или читайте меня в twitter
11 комментариев:
Ключевым недостатком XStream для меня стало то, что он не может создавать JSON код вида [var:result, var2:result], а только вида {root:[var:result, var2:result]}, были и другие заморочки с преобразованием типов, которые я решать уже не стал.
Поэтому я воспользовался библиотечкой Jackson (http://jackson.codehaus.org/), которая прекрасно "искаропки" интегрируется со spring-mvc и проблем с которой пока ещё не было.
Хм, спасибо за наводку, посмотрю Jackson.
Мне и то и другое показалось неудобным.
Допустим, у меня есть ряд бизнес объектов. В разных view мне их надо отобразить по разному и в разных комбинациях. Описанные преобразования накладывают ограничения на мои объекты. Приходиться делать специальные объекты обертки и копировать нужные свойства в нужном порядке. Ситуация ухудшается при использовании нескольких разных javascript компонентов.
Самым простым и легко расширяемый способом преобразования показался jsp. Понятно, что в случае изменений бизнес объекта, придется попотеть, но к счастью это случается не часто.
Попробуем так, спасибо!
Кай, неправда ваша! если немного погуглить (что я и сделал, когда столкнулся с такой же "проблемой"), то получаем вот такой код при объявлении:
XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
Скажите, а не проще ли использовать XSLT для преобразования XML в JSON?
Константин, покажите универсальный пример, подходящий под XML любой структуры - может быть и правда проще будет.
Сомневаюсь, что существует такой "универсальный пример, подходящий под XML любой структуры", Виктор. Но мне кажется, что в большинстве случаев требуется нечто большее, чем прямое преобразование данных из одного формата в другой (XML <-> JSON, например). В моей практике я постоянно сталкиваюсь с тем, что получаемые данные надо ещё как-то модифицировать перед представлением (например, gjkexbnm новые значения на основе имеющихся, создать из плоского списка дерево и т. п.). Вот я и спрашиваю, что в данном случае будет эффективнее: XSLT-преобразование или использование XStream?
ИМХО здесь надо тестировать причем в каждом конкретном случае результаты могут быть разные. Опять же, что значит "Эффективнее"
Эффективнее, в моём понимании, значит быстрее и с наименьшим расходованием ресурсов.
Стоп, народ.
Если мы говорим про сериализацию, то при чем тут "надо ещё модифицировать перед представлением".
А если мы говорим о преобразовании данных, то тут уже выбирать под задачу надо - где-то XSLT сподручнее будет, а где-то и XStream. ни то ни другое не есть панацея от всех "бед"
Отправить комментарий
Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!