Как конвертировать модели Play Framework в XML и JSON?
Существует ли в платформе воспроизведения Нативный или Рекомендуемый способ преобразования моделей Play в XML/JSON? Что-то похожее на JAXB или Jackson.
Некоторые люди рекомендуют шаблонный подход, но это очень многословно и не гарантирует корректного XML/JSON.
Воспроизвести документацию по XML просто показывает, что XML-ответ строится с использованием конкатенации строк следующим образом:
return ok("<message \"status\"=\"OK\">Hello " + name + "</message>");
Аналогично, Play Documentation на JSON показывает, что объект JSON строится по одной строке за раз.
ObjectNode result = Json.newObject();
result.put("status", "OK");
result.put("message", "Hello " + name);
Существует ли Стандартный способ сериализации моделей в XML/JSON с помощью Play?
Есть ли официальная форматная документация на эту тему?
Ответы
Ответ 1
Короткий ответ: Jackson для JSON и JAXB для XML
Play сам не предоставляет никакой документации по моделям сортировки, но поставляется с Сторонних библиотек, которые могут выполнять эту работу.
JSON:
Модель:
public class User extends Model {
public String username;
public Long age;
@JsonIgnore
public String password; // field won't be marshalled
}
Отметьте его JSON с помощью метода jackson ObjectMapper.writeValueAsString().
import org.codehaus.jackson.map.ObjectMapper;
//
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(country);
Выход JSON:
{
"username" : "John Smith",
"age" : "25"
}
XML:
Необходимо проявлять осторожность из-за того, как Play генерирует геттеры и сеттеры для него модели под капотом. Вы не увидите получателей и сеттеров в коде, но они существуют во время выполнения.
В этой модели важно установить аннотацию XmlAccessorType в PROPERTY. Это говорит JAXB для сериализации из getter/seters, а не из базовых полей.
@XmlAccessorType(XmlAccessType.PROPERTY)
Мы также должны добавить аннотацию @XmlRootElement, которая указывает имя корневого XML node:
@XmlRootElement(name = "UserRoot")
Чтобы опустить поле, мы должны добавить аннотацию @XmlTransient к получателю. Поскольку в исходном коде отсутствует getter, мы должны добавить один для каждого поля, которое мы хотим опустить.
@XmlAccessorType(XmlAccessType.PROPERTY)
public class User extends Model {
public String username;
public Long age;
@JsonIgnore
public String password;
@XmlTransient // This means ignore this property
public String getPassword() {
return this.password;
}
}
Маршаллинг выполняется классами JAXB Marshaller и JAXBContext
JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
// Use linefeeds and indentation in the outputted XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(user, System.out);
Вывод:
<UserRoot>
<name>John Smith</name>
<age>25</age>
</UserRoot>
Резюме:
Воспроизвести документы в формате XML и Воспроизвести документы на JSON Предоставлять некоторую информацию о работе с json/xml, но, похоже, нет ни одного Play Docs, описывающего, как сделать Маршаллинг. Для этого мы должны посмотреть сторонние библиотеки и документацию.
Ответ 2
Для JSON я бы предложил использовать... org.codehaus.jackson
, поскольку он доступен как play.libs.Json
в Play 2/x
@см.: Json Doc
Для XML
- шаблонный подход достаточно справедлив, так как вы можете отобразить правильный XML с представлением.
Edit:
Json и Ebean
К сожалению, у Ebean есть проблемы с сериализацией своих объектов в JSON, поэтому я всегда использую выделенный внутренний класс (в целевой модели, которая содержит только поля, которые должны быть отправлены в Json), т.е. для User
модель:
public static class ForJson {
public Long id;
public String name;
public String email;
public ForJson(User user) {
this.id = user.id;
this.name = user.name;
this.email=user.email;
}
}
маршруты:
GET /users/all.json controllers.Application.listUsersJson
GET /users/all-details.json controllers.Application.listUsersJsonWithDetails
GET /users/:id.json controllers.Application.singleUserJson(id: Long)
действия:
public static Result listUsersJson() {
List<User.ForJson> usersToJson = new ArrayList<>();
for (User user : User.find.all()) {
usersToJson.add(new User.ForJson(user));
}
return ok(Json.toJson(usersToJson));
}
public static Result singleUserJson(Long id) {
User.ForJson userForJson = new User.ForJson(User.find.byId(id));
return ok(Json.toJson(userForJson));
}
public static Result listUsersJsonWithDetails() {
Map<String, Object> details = new LinkedHashMap<>();
List<User.ForJson> usersToJson = new ArrayList<>();
for (User user : User.find.all()) {
usersToJson.add(new User.ForJson(user));
}
details.put("date", new Date());
details.put("count", usersToJson.size());
details.put("users", usersToJson);
return ok(Json.toJson(details));
}
Да, я знаю, может быть, это redunt и кодирование, но у меня есть хотя бы правильный JSON-выход, и мне не нужно создавать JSON по строкам в каждом действии.
XML:
HTML-символы не нарушают рендеринг правильного XML, так как по умолчанию воспроизводятся шаблоны воспроизведения, поэтому вместо <
, >
, "
он будет использовать <
, >
, "
внутри XML node:
<sample>Say "ellou"<sample>
Отметьте Экранирование абзаца в документе docs (внизу страницы).
Чем больше вы можете использовать частичные шаблоны - теги, чтобы убедиться, что один элемент будет отформатирован точно так же в обоих: users/1.xml
и users/all.xml
Ответ 3
Существует лучший способ для преобразования JSON.
User user = new User("...");
String jsonString = Ebean.json().toJson(user);