en Java cuando se utiliza la anotaciónJAX-RS JSON de salida bastante
@Produces("application/json")
la salida no está formateada en formato legible por humanos. ¿Cómo logro eso?
en Java cuando se utiliza la anotaciónJAX-RS JSON de salida bastante
@Produces("application/json")
la salida no está formateada en formato legible por humanos. ¿Cómo logro eso?
Crea esta clase en cualquier lugar de tu proyecto. Se cargará en la implementación. Observe el .configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
que configura el asignador para formatear la salida.
Para Jackson 2.0 y posterior, reemplace las dos líneas .configure()
con éstos: .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
.configure(SerializationFeature.INDENT_OUTPUT, true);
y cambiar su importación en consecuencia.
package com.secret;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
/**
*
* @author secret
*/
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper;
public JacksonContextResolver() throws Exception {
this.objectMapper = new ObjectMapper();
this.objectMapper
.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
}
@Override
public ObjectMapper getContext(Class<?> objectType) {
return objectMapper;
}
}
Tenga en cuenta que el formateo tiene un efecto negativo en el rendimiento.
Solo para el registro, si desea habilitar la salida bonita solo para algunos recursos, puede usar the @JacksonFeatures annotation en un método de recursos.
Aquí es ejemplo:
@Produces(MediaType.APPLICATION_JSON)
@JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT })
public Bean resource() {
return new Bean();
}
'@ JacksonFeatures' solo está disponible en un método, no en una clase. – NomeN
Partiendo de útil respuesta de DaTroop, aquí es otra versión que permite elegir entre JSON optimizado y formato JSON basado en la ausencia o presencia de un parámetro "bonita":
package test;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
private ObjectMapper prettyPrintObjectMapper;
private UriInfo uriInfoContext;
public JacksonContextResolver(@Context UriInfo uriInfoContext) throws Exception {
this.uriInfoContext = uriInfoContext;
this.prettyPrintObjectMapper = new ObjectMapper();
this.prettyPrintObjectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
}
@Override
public ObjectMapper getContext(Class<?> objectType) {
try {
MultivaluedMap<String, String> queryParameters = uriInfoContext.getQueryParameters();
if(queryParameters.containsKey("pretty")) {
return prettyPrintObjectMapper;
}
} catch(Exception e) {
// protect from invalid access to uriInfoContext.getQueryParameters()
}
return null; // use default mapper
}
}
Si bien esta es una buena solución, solo funciona * la primera vez * se llama un recurso. Después de eso, el proveedor ha sido registrado y usted está atascado con la impresión bonita (o no). Para una flexibilidad real, elija una solución de filtro. – mvreijn
Así es como se puede hacer adecuadamente salida jSON condicional/no bonita basada en la presencia de "bonita" en la cadena de consulta.
Crear una PrettyFilter
que implementa ContainerResponseFilter
, que se ejecutará en cada petición :
@Provider
public class PrettyFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException {
UriInfo uriInfo = reqCtx.getUriInfo();
//log.info("prettyFilter: "+uriInfo.getPath());
MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
if(queryParameters.containsKey("pretty")) {
ObjectWriterInjector.set(new IndentingModifier(true));
}
}
public static class IndentingModifier extends ObjectWriterModifier {
private final boolean indent;
public IndentingModifier(boolean indent) {
this.indent = indent;
}
@Override
public ObjectWriter modify(EndpointConfigBase<?> endpointConfigBase, MultivaluedMap<String, Object> multivaluedMap, Object o, ObjectWriter objectWriter, JsonGenerator jsonGenerator) throws IOException {
if(indent) jsonGenerator.useDefaultPrettyPrinter();
return objectWriter;
}
}
}
Y más o menos eso es todo!
Deberá asegurarse de que esta clase sea utilizada por Jersey mediante el escaneo automático de paquetes o registrada manualmente.
Pasé algunas horas tratando de lograr eso y descubrí que nadie había publicado antes una solución lista para usar.
Esta es la mejor solución, de lejos, me gustaría poder votar dos veces. No olvides usar 'register (PrettyFilter.class)' en tu 'ResourceConfig'. – mvreijn
Si está utilizando la primavera, entonces se puede establecer la propiedad a nivel mundial
spring.jackson.serialization.INDENT_OUTPUT=true
Más información en https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
lo JSON-serializador está usando? –
Simplemente usando el estándar netbeans. Creado con el asistente "nuevos servicios web RESTful de Entity Classes" Soy nuevo, pero creo que es jackson? – niklas
Sí, es Jackson – DaTroop