Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream JSON output in Spring MVC

My application is built using Spring Boot(1.3.3.RELEASE) with Spring MVC, Spring data JPA Hibernate. MySql is the database and Jackson is the JSON serializer. On java 8.

I want to return a huge data set in my controller method. Instead of retrieving all the data and then passing into the Jackson serializer, I want to return a stream of objects like below:

@RequestMapping(value = "/candidates/all", method = RequestMethod.GET)
public Stream<Candidate> getAllCandidates(){
    try { 
        return candidateDao.findAllByCustomQueryAndStream();
    } catch(Exception e){
        LOG.error("Exception in getCandidates",e);
    }
    return null;
}

my DAO is like below:

@Query("select c from Candidate c")
public Stream<Candidate> findAllByCustomQueryAndStream();

However, Jackson is serializing the stream object instead of the contents of the stream. The actual output below:

{"parallel" : false}

How can I instruct Jackson to serialize the content and not the stream object?

like image 697
Vasco Avatar asked May 11 '16 07:05

Vasco


People also ask

Can I write a JSON string directly to the response stream?

But it is inefficient to put together the JSON string, only to have Spring write it to the response's output stream. Instead, I can write it directly to the response output stream like this: But it seems like there would be a better way to do this than having to resort to passing the HttpServletResponse into the handler method.

Does Spring MVC use JSON?

01 Apr 2018, 22:34 Spring MVC / REST To adhere to guidelines or requirements, API designers may want to control how JSON/XML responses are formatted. Spring Webmakes use of Jackson to perform JSON/XML serialization.

How to output JSON data in spring 3 using Jackson Library?

P.S In Spring 3, to output JSON data, just puts Jackson library in the project classpath. 1. Project Dependencies Get Jackson and Spring dependencies.

How can I customize the JSON/XML output format in Spring Web API?

To adhere to guidelines or requirements, API designers may want to control how JSON/XML responses are formatted. Spring Webmakes use of Jackson to perform JSON/XML serialization. Therefore, to customize our output format, we must configure the Jackson processor. Spring Web offers XML-based or Java-based approaches to handling configuration.


3 Answers

There is a proposed solution at https://github.com/FasterXML/jackson-modules-java8/issues/3 which may be the better way to go.

I'll not paste the code in here, as it may get updated in that issue.

So far, I've not found any issues with that proposed code which I've added in with other modules such as the Jdk8Module for Optional as

jacksonObjectMapper.registerModule(new StreamModule());
like image 65
NealeU Avatar answered Oct 17 '22 22:10

NealeU


Return Iterable<Candidate> from your controller

Stream converts to an iterator by Iterable<X> iterable = stream::iterator;

@RequestMapping(value = "/candidates/all", method = RequestMethod.GET)
public Iterable<Candidate> getAllCandidates(){
    ...

        return candidateDao.findAllByCustomQueryAndStream()::iterator;
like image 22
epox Avatar answered Oct 17 '22 20:10

epox


Thanks to this I was able to solve the issue.

I had provide a custom httpMessageConverter that understands how to handle streams. Like so:

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper =jsonConverter.getObjectMapper();
    SimpleModule module = new SimpleModule("Stream");
    module.addSerializer(Stream.class, 
        new JsonSerializer<Stream>() {
            @Override
            public void serialize(Stream value, JsonGenerator gen, SerializerProvider serializers)
            throws IOException, JsonProcessingException {
                 serializers.findValueSerializer(Iterator.class, null)
                .serialize(value.iterator(), gen, serializers);
            }
    });
 
    objectMapper.registerModule(module);
    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}
like image 14
Vasco Avatar answered Oct 17 '22 22:10

Vasco