Подтвердить что ты не робот

Отключить язык приложений гипертекста (HAL) в JSON?

Использование Spring Data REST с JPA в версии 2.0.2.RELEASE.

Как отключить язык гипертекстовых приложений (HAL) в JSON? http://stateless.co/hal_specification.html

Я уже много пробовал, но безрезультатно. Например, я установил заголовки Accept и Content-type в "application/json" вместо "application/hal + json", но я все еще получаю содержимое JSON с гиперссылками.

Например, я хотел бы получить что-то вроде:

{
"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
     }
}

Вместо:

{
"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"
     }
}
}

Спасибо за вашу помощь.

4b9b3361

Ответ 1

(Hyper) типы носителей

Настройки по умолчанию для Spring Data REST используют HAL в качестве формата представления гипермедиа по умолчанию, поэтому сервер будет возвращать следующие данные для указанных заголовков Accept:

  • Нет заголовка → application/hal+json → HAL
  • application/hal+jsonapplication/hal+json → HAL
  • application/jsonapplication/json → HAL (это то, что настраивается по умолчанию)
  • application/x-spring-data-verbose+jsonapplication/x-spring-data-verbose+json → a Spring Формат данных (с помощью links для контейнера ссылок и content в качестве обертки для элементов коллекции.

Если вы настроите RepositoryRestConfiguration.setDefaultMediaType(…) на не-HAL-формат, сервер вернет формат JSON, специфичный для данных Spring, если вы явно не запросите application/hal+json. Разумеется, вариант конфигурации, вероятно, немного вводит в заблуждение, поэтому я добавил DATAREST-294, чтобы улучшить это. Проблема была решена в 2.1 RC1 (Dijkstra) 2014.

Обратите внимание, что нам действительно нужен формат гипермедиа, чтобы иметь возможность выражать отношения между управляемыми ресурсами и обеспечивать возможность обнаружения сервера. Таким образом, вы не сможете полностью избавиться от него. Это связано в основном с тем, что вы можете легко свернуть сервер, если вы обнаружите объекты, которые имеют двунаправленные отношения или составляют огромный граф объектов.

Встраивание связанных объектов

Если вы никогда не хотите иметь секторы, связанные с ними и всегда встраивать их, один параметр состоит в том, чтобы просто исключить SectorRepository из экспорта в качестве ресурса REST в первую очередь. Вы можете достичь этого, аннотируя интерфейс репозитория с помощью @RepositoryRestResource(exported = false).

Чтобы получить представление, возвращенное, как вы разместили в своем нижнем примере, посмотрите на проекции, введенные в Spring Data REST 2.1 M1, Это в основном позволяет создавать дополнительные представления на ресурсе, который может отличаться от стандартного с помощью простого интерфейса.

В основном вы определяете интерфейс:

@Projection(name = "foo", types = YourDomainClass.class)
interface Inlined {

  // list all other properties

  Sector getSector();
}

Если вы поместите этот интерфейс в (дополнительный) пакет вашего класса домена или вручную зарегистрируйте его через RepositoryRestConfiguration.projectionConfiguration(), ресурсы, отображающие YourDomainClass, будут принимать параметр запроса projection, так что передача в foo в этом пример предоставил бы встроенное представление так, как вы хотите.

Этот коммит содержит больше информации об этой функции в целом, this commit имеет пример проекции.

Ответ 2

Итак, вы хотите 2 вещи:

1) избавиться от поля _links
2) включить поле соответствующего sector

Возможное решение (у меня работает: D)

1) избавиться от _links
Для этого создайте класс ниже:

[... 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();
            }
        };
    }
}

и использовать его, например:

[... package declaration, imports ...]
@SpringBootApplication
@Import({MyRepositoryRestMvcConfiguration.class})
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Я почти уверен (99%, но не протестирован), что вам не понадобится этот класс для удаления _links для связанных сущностей/сущностей, включенных в способ, который показывает следующая точка (2).

2) включить поле соответствующего sector
Для этого вы можете использовать выдержки (специально созданные для этого сценария). Поскольку пример Spring настолько красноречив, и просто глупо просто копировать его здесь, я просто укажу на него: https://docs.spring.io/spring-data/rest/docs/3.1.x/reference/html/#projection -excerpts.excerpting-общедоступные данные.
Но для удобства и удобства я вставлю основные части весеннего примера:

@Projection(name = "inlineAddress", types = { Person.class }) 
interface InlineAddress {
  String getFirstName();
  String getLastName();
  Address getAddress(); 
}

увидеть на Javadoc проекционного, что types означают тип типа проекции, связанный с.
Выдержка может быть использована следующим образом:

@RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository<Person, Long> {}

чтобы получить это (когда также используется MyRepositoryRestMvcConfiguration):

{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "address" : { 
    "street": "Bag End",
    "state": "The Shire",
    "country": "Middle Earth"
  }
}

Для вас sector является эквивалентом address.

Финальные заметки

При возврате массивов поле _links не будет удалено (это слишком навязчиво для этого); в итоге у вас будет что-то вроде этого:

{
    "_embedded" : {
        "persons" : [ {person1}, {person2}, ..., {personN} ]
    },
    "_links" : {
        e.g. first, next, last, self, profile
    },
    "page" : {
      "size" : 1,
      "totalElements" : 10,
      "totalPages" : 10,
      "number" : 0
    }
}

Как вы можете видеть, даже если бы _links удалили _links этого все равно будет недостаточно; _embedded было бы также хотеть, чтобы _embedded заменялось persons что приводило бы к менее поддерживаемому коду (слишком много весенних навязчивых переопределений). Но если кто-то действительно хочет этого, он должен начать проверять RepositoryRestMvcConfiguration и RepositoryEntityController.getCollectionResource.

Spring развивается, поэтому я чувствую необходимость указать, что это работает по крайней мере:

spring-data-rest-webmvc 3.1.3.RELEASE

или, если вы предпочитаете весеннюю загрузку:

spring-boot-starter-parent 2.1.1.RELEASE