Довольно простой вопрос, трудно найти ответ:
Я хочу сериализовать в JSON мои сущности POJO JPA со ссылками, подобными Dojo, чтобы использовать его с dojox.data.JsonRestStore.
Серверная часть сделана с использованием Spring MVC и HttpConverters, чтобы сделать его веб-приложением RESTfull. Я использую JacksonJson для преобразования сущностей JPA в JSON.
Как и у многих людей, у меня есть проблемы с несколькими ссылками. @JsonBackReference и @JsonManagedReference не справляются с задачей!
Рассматривая этот базовый пример:
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable=false)
private String field;
@OneToMany(mappedBy = "b")
private List<B> bs;
}
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private A a;
}
С помощью базового конвертера Джексона Джсона вы получаете что-то вроде этого (учитывая, что вы поместили @JsonBackReference и @JsonManagedReference):
{ id:1, fieldB:"bbbbb", a: { id:1, fieldA: "aaaaaa" }}
В конкретном приложении иметь список bs для объектов A в большинстве случаев бессмысленно. Но важно знать, что за объект A находится в поле B.a (по крайней мере, для меня).
Теперь, проблема заключается в том, что ссылки копируются, и вы можете получить какой-то серьезный большой JSON без большого количества данных.
Dojo Framework предоставляет эталонный стандарт, объясненный здесь: http://www.sitepen.com/blog/2008/06/17/json-referencing-in-dojo/ и
http://dojotoolkit.org/reference-guide/dojox/data/JsonRestStore.html.
Так что я ищу способ определить это следующим образом:
{ id:1, fieldB:"bbbbb", a: { $ref: "getA/1"}}
Первая проблема: Джексон, очевидно, не может знать, какой URL вы будете использовать для ссылки.
Чтобы решить эту проблему, я сделал очень простой интерфейс, подобный этому:
public interface EntityWithId {
public Long getId();
public void setId(Long id);
}
Этот интерфейс был реализован всеми моими сущностями, и я сделал этот очень простой JsonSerializer:
public class EntityIdSerializer extends JsonSerializer<EntityWithId> {
@Override
public void serialize(EntityWithId value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("$ref", "db/" + value.getClass().getSimpleName() + "/" + value.getId().toString());
jgen.writeEndObject();
}
}
С этими двумя я получил желаемый JSON, добавив @ JsonSerialize (используя = EntityIdSerializer.class) к полям @ ManyToOne .
Нет ли более стандартного подхода? Dojo dojox.data.JsonRestStore звучит очень многообещающе, поскольку вы можете комбинировать его с большим количеством виджетов Dijits, но действительно ли это хорошая вещь, которую можно попробовать и попробовать? Разве мое приложение REST не будет сильно ограничивать Dojo?
Спасибо за ваши ответы!