1

I have list of objects returning like the below format (not pretty).

{"data":[{"id":1,"firstName":"Bill","lastName":"Johnson"}]

I would like it to show like this (pretty).

{
    "data":[{
        "id":1,"
        firstName":"Bill",
        "lastName":"Johnson"
        }]
}

This is my method signature, along with my call to the service to query the DB and the return that prints json to screen.

public @ResponseBody ResponseEntity<ResponseData<List<NameSearchDTO>>> getInfo(@PathVariable String code, @PathVariable String idType)

ResponseData<List<NameSearchDTO>> response = new ResponseData<>();

List<NameSearchDTO> results = officeService.getByCode(code, idType); 
if (!results.isEmpty()) {
            response.setData(results);
            response.setStatus(Enum.SUCCESS.getDescription());
            response.setMessage(Enum.STATUS_SUCCESS.getDescription());
return new ResponseEntity<>(response, HttpStatus.OK);
}

The ResponseData Class implements Serializable. Does this make it "true" JSON as I'm not using Jackson or any other JSON library?

How do I pass the response to the below ObjectMapper to make it pretty?

ObjectMapper jacksonMapper = new ObjectMapper();
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

Or do I need to create some sort of JSONHelper class?

ResponseData Class

public class ResponseData <E> implements Serializable{


    private E data;
    private String status;
    private String message;
    private boolean hasValidationError = false;

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public boolean getHasValidationError(){
        return hasValidationError;
    }

    public void setHasValidationError(boolean hasValidationError){
        this.hasValidationError = hasValidationError;
    }
}
Rakesh
  • 4,004
  • 2
  • 19
  • 31
Angular_Newbie
  • 415
  • 1
  • 9
  • 25
  • See [Pretty print JSON output of Spring Boot Actuator endpoints](https://stackoverflow.com/questions/24503790/pretty-print-json-output-of-spring-boot-actuator-endpoints) and [Spring MVC](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html) Generally, you can customise your `Jackson` `ObjectMapper` but it depends what version of `Spring` do you use, configuration, libraries. `Serialisable` interface is not needed and it does not make it `true` `JSON`. – Michał Ziober Mar 12 '19 at 20:11
  • Possible duplicate of [Jackson2ObjectMapperBuilder enable field visibility ANY](https://stackoverflow.com/questions/29807879/jackson2objectmapperbuilder-enable-field-visibility-any) – Michał Ziober Mar 12 '19 at 20:29

6 Answers6

3

I think the best way beautify the json string is as follows using Jackson:

import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(yourObject)
Rakesh
  • 4,004
  • 2
  • 19
  • 31
  • @Angular_Newbie this isn't Spring specific, and you'll have to repeat it every time. A lot of duplication for nothing. – LppEdd Mar 15 '19 at 19:05
  • I agree. I will attempt using your third and fourth option. Looks like Spring magic. – Angular_Newbie Mar 15 '19 at 19:33
  • @Angular_Newbie well, let me know in case you need help. As a general rule, if you're on Spring, stick to the Spring way. – LppEdd Mar 15 '19 at 21:05
  • @LppEdd The solution is just for beautifying Json. You can create ObjectMapper in in context once and use it across your application. I am not sure what you mean by duplication for nothing? – Rakesh Mar 15 '19 at 21:20
2

You can define

  • a MappingJacksonHttpMessageConverter (no need for Spring Boot)
  • a Jackson2ObjectMapperBuilder Bean
  • a simple ObjectMapper Bean annotated with @Primary
  • a configuration property (Spring Boot - skip to this one for the simplest).

For the first solution you need to implement the WebMvcConfigurer interface
(skip this one if you're on Spring Boot)

@Configuration
class CustomWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
        final ObjectMapper mapper =
                new Jackson2ObjectMapperBuilder()
                        .indentOutput(true)
                        .build();

        // Or build ObjectMapper without the Spring builder, it's the same thing
        converters.add(new MappingJackson2HttpMessageConverter(mapper));
    }
}

The key is this line

indentOutput(true)

Which actually manipulates the underlying ObjectMapper configuration

public Jackson2ObjectMapperBuilder indentOutput(boolean indentOutput) {
    this.features.put(SerializationFeature.INDENT_OUTPUT, indentOutput);
    return this;
}

The second one is a bit simpler

@Bean
Jackson2ObjectMapperBuilder jackson() {
   return new Jackson2ObjectMapperBuilder().indentOutput(true);
}

The third one is even simpler, just

@Bean
@Primary
ObjectMapper objectMapper() {
   final ObjectMapper mapper = new ObjectMapper();
   mapper.enable(SerializationFeature.INDENT_OUTPUT);  
   return mapper;
}

A fourth way consists only on using the configuration property

spring.jackson.serialization.indent_output=true
LppEdd
  • 20,274
  • 11
  • 84
  • 139
1

You tagged gson so you can use this library to display .json file:

import org.json.JSONObject

val json = "{\"data\":[{\"id\":1,\"firstName\":\"Bill\",\"lastName\":\"Johnson\"}]\n"

val jsonObject = JSONObject(json)

println(jsonObject.toString(4))

https://github.com/google/gson

Boken
  • 4,825
  • 10
  • 32
  • 42
1

I believe you are looking for Gson's pretty printing functionality. Being that you've tagged your question with gson, I presume that its okay if you use the library. Mkyong has a great tutorial on pretty printing Here.

The essential line from the tutorial is:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
armitus
  • 712
  • 5
  • 20
1

No need to import a bunch of new stuff. Only what system may complain about (if any). But if you're already using Jackson, and wanted to use the mapper -> just use "readValue" or "writeValue" right?

This link explains a lot of ways to do this: Jackson Examples

Remove your result assignment and use direct conversion with Mapper

ObjectMapper jacksonMapper = new ObjectMapper();
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
List<NameSearchDTO> mappedResults = mapper.readValue(officeService.getByCode(code, idType) ,new TypeReference<List<NameSearchDTO>>() {} );

then add that to your result return. (seems a bit clunky having that added container class, but I don't pretend to know your requirements).

if (!mappedResults.isEmpty()) {
            response.setData(mappedResults);
            response.setStatus(Enum.SUCCESS.getDescription());
            response.setMessage(Enum.STATUS_SUCCESS.getDescription());
return new ResponseEntity<>(response, HttpStatus.OK);
BoltX
  • 21
  • 6
0

You can use toString(int indentFactor) from JSONObject

Mounica
  • 1
  • 1