'Disable Hypertext Application Language (HAL) in JSON?

Using Spring Data REST with JPA in version 2.0.2.RELEASE.

How can I disable Hypertext Application Language (HAL) in the JSON ? http://stateless.co/hal_specification.html

I have tried many things already, but to no avail. For example, I have set Accept and Content-type headers to "application/json" instead of "application/hal+json" but I still receive the JSON content with hyper links.

For example, I'd like to get something like:

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

Instead of:

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

Thanks for your help.



Solution 1:[1]

So you want 2 things:

1) get rid of _links field
2) include the related sector field

Possible solution (works for me :D)

1) get rid of _links
For this create the class below:

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

and use it e.g.:

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

I'm pretty sure (99%, but not tested) that you won't need this class for removing the _links for the related entity/entities included the way next point (2) is showing.

2) include the related sector field
For this you could use Excerpts (especially made for this scenario). Because the Spring example is so eloquent and it's silly to just copy it here I'll just point it: https://docs.spring.io/spring-data/rest/docs/3.1.x/reference/html/#projections-excerpts.excerpting-commonly-accessed-data.
But just for the record and your convenience I'll paste the main parts of the spring example:

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

see at Projection javadoc that types means The type the projection type is bound to.
The excerpt could be used this way:

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

in order to get this (when also using MyRepositoryRestMvcConfiguration):

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

For you the sector is the equivalent of address.

Final notes

When returning arrays the _links field won't be removed (it's too intrusive to do it); in the end you'll have something like this:

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

As you can see even if we'd have _links removed that still won't be enough; one would probably also want _embedded replaced by persons which would lead to less maintainable code (too much spring intrusive overrides). But if one really wants these too he should start checking RepositoryRestMvcConfiguration and RepositoryEntityController.getCollectionResource.

Spring is evolving so I feel the need to point that this works with at least:

spring-data-rest-webmvc 3.1.3.RELEASE

or, if you prefeer spring boot version:

spring-boot-starter-parent 2.1.1.RELEASE

Solution 2:[2]

If you want to delete _links do the following (worked for me):

  1. Go to your pom.xml and delete the following dependency:

    spring-boot-starter-data-rest

  2. Make an "Update project" to update the pom.xml changes.

Now it will be use your own controller for the api rest, deleting _self, _links..., that alike this:

[... package declaration, imports ...]
@RestController
@RequestMapping("/series")
public class SerieController {
    @Autowired
    private SerieRepositorio serieRepositorio;
    
    public SerieController(SerieRepositorio serieRepositorio) {
        this.serieRepositorio = serieRepositorio;
    }

    @GetMapping
    public Iterable<Serie> getAllSeries() {
        return serieRepositorio.findAll();
    }
   }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 St3g4n0