Utilisation de Spring Data REST avec JPA dans la version 2.0.2.RELEASE.
Comment puis-je désactiver le langage d'application hypertexte (HAL) dans le JSON? http://stateless.co/hal_specification.html
J'ai déjà essayé beaucoup de choses, mais en vain. Par exemple, j'ai défini les en-têtes Accept et Content-type sur "application/json" au lieu de "application/hal + json" mais je reçois toujours le contenu JSON avec des hyperliens.
Par exemple, j'aimerais obtenir quelque chose comme:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"sector" : {
"description" : "Marketing",
"average profit": 545656665,
"average employees": 75,
"average profit per employee": 4556
}
}
Au lieu de:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"_links" : {
"self" : {
"href" : "http://localhost:8080/app/companies/1"
},
"sector" : {
"href" : "http://localhost:8080/app/companies/1/sector"
}
}
}
Merci de votre aide.
Les paramètres par défaut de Spring Data REST utilisent HAL comme format de représentation hypermédia par défaut, donc le serveur renverra les éléments suivants pour les en-têtes Accept
donnés:
application/hal+json
-> HALapplication/hal+json
-> application/hal+json
-> HALapplication/json
-> application/json
-> HAL (c'est ce que la configuration par défaut)application/x-spring-data-verbose+json
-> application/x-spring-data-verbose+json
-> un format spécifique aux données Spring (en utilisant links
pour le conteneur de liens et content
comme wrapper pour les éléments de la collection.Si vous configurez RepositoryRestConfiguration.setDefaultMediaType(…)
dans un format non HAL, le serveur renverra le format JSON spécifique de Spring Data, sauf si vous demandez explicitement application/hal+json
. Certes, l'option de configuration est probablement un peu trompeuse, j'ai donc déposé DATAREST-294 pour améliorer cela. Le problème a été résolu dans 2.1 RC1 (Dijkstra) 2014.
Notez que nous avons effectivement besoin d'un format hypermédia pour pouvoir exprimer les relations entre les ressources gérées et permettre la découverte du serveur. Il n'y a donc aucun moyen que vous puissiez vous en débarrasser complètement. Cela est principalement dû au fait que vous pouvez facilement planter le serveur si vous exposez des entités qui ont des relations bidirectionnelles ou si vous créez un énorme graphique d'objet.
Si vous ne voulez jamais avoir de secteurs liés à et toujours en ligne, une option consiste simplement à exclure le SectorRepository
de l’exportation en tant que ressource REST en premier lieu. Vous pouvez Pour ce faire, annotez l'interface du référentiel avec @RepositoryRestResource(exported = false)
.
Pour obtenir une représentation retournée comme vous l'avez publié dans votre exemple inférieur, jetez un œil à la fonctionnalité projections introduite dans Spring Data REST 2.1 M1. Elle vous permet essentiellement de créer en option vues sur une ressource qui peut différer de celle par défaut via une interface simple.
Vous définiriez essentiellement une interface:
@Projection(name = "foo", types = YourDomainClass.class)
interface Inlined {
// list all other properties
Sector getSector();
}
Si vous placez cette interface dans un (sous) package de votre classe de domaine ou l'enregistrez manuellement via RepositoryRestConfiguration.projectionConfiguration()
les ressources exposant YourDomainClass
accepteront un paramètre de requête projection
afin que passer foo
dans cet exemple rendrait la représentation en ligne comme vous le souhaitez.
Ce commit a plus d'informations sur la fonctionnalité en général, ce commit a un exemple de projection défini.
Vous voulez donc 2 choses:
1) se débarrasser de _links
champ
2) inclure le champ sector
associé
Solution possible (fonctionne pour moi: D)
1) se débarrasser de _links
Pour cela, créez la classe ci-dessous:
[... package declaration, imports ...]
public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
public MyRepositoryRestMvcConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
super(context, conversionService);
}
@Bean
protected LinkCollector linkCollector() {
return new LinkCollector(persistentEntities(), selfLinkProvider(), associationLinks()) {
public Links getLinksFor(Object object, List<Link> existingLinks) {
return new Links();
}
};
}
}
et l'utiliser par exemple:
[... package declaration, imports ...]
@SpringBootApplication
@Import({MyRepositoryRestMvcConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Je suis sûr (99%, mais non testé) que vous n'aurez pas besoin de cette classe pour supprimer le _links
pour l'entité/les entités associées inclus la façon dont le point suivant (2) est affiché.
2) inclure le champ sector
associé
Pour cela, vous pouvez utiliser extraits (spécialement conçu pour ce scénario). Parce que l'exemple de Spring est si éloquent et qu'il est idiot de le copier ici, je vais juste le pointer: https://docs.spring.io/spring-data/rest/docs/3.1.x/reference/ html/# projections-excerpts.excerpting-common-access-data .
Mais juste pour mémoire et pour votre commodité, je vais coller les parties principales de l'exemple du printemps:
@Projection(name = "inlineAddress", types = { Person.class })
interface InlineAddress {
String getFirstName();
String getLastName();
Address getAddress();
}
voir à Projection javadoc que types
signifie Le type auquel le type de projection est lié.
Le extrait pourrait être utilisé de cette façon:
@RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository<Person, Long> {}
afin d'obtenir ceci (en utilisant également MyRepositoryRestMvcConfiguration):
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"address" : {
"street": "Bag End",
"state": "The Shire",
"country": "Middle Earth"
}
}
Pour vous, le sector
est l'équivalent de address
.
Notes finales
Lors du retour des tableaux, le _links
le champ ne sera pas supprimé (c'est trop intrusif pour le faire); à la fin, vous aurez quelque chose comme ça:
{
"_embedded" : {
"persons" : [ {person1}, {person2}, ..., {personN} ]
},
"_links" : {
e.g. first, next, last, self, profile
},
"page" : {
"size" : 1,
"totalElements" : 10,
"totalPages" : 10,
"number" : 0
}
}
Comme vous pouvez le voir, même si nous aurions _links
supprimé qui ne sera toujours pas suffisant; on voudrait probablement aussi _embedded
remplacé par persons
ce qui conduirait à un code moins facile à maintenir (trop de remplacements intrusifs de ressort). Mais si on le veut vraiment aussi, il devrait commencer à vérifier RepositoryRestMvcConfiguration
et RepositoryEntityController.getCollectionResource
.
Le printemps évolue donc je ressens le besoin de souligner que cela fonctionne avec au moins:
spring-data-rest-webmvc 3.1.3.RELEASE
ou, si vous préférez la version Spring Boot:
spring-boot-starter-parent 2.1.1.RELEASE