in Java quando uso l'annotazioneJAX-RS JSON abbastanza uscita
@Produces("application/json")
l'uscita non è formattato in formato leggibile. Come posso farlo?
in Java quando uso l'annotazioneJAX-RS JSON abbastanza uscita
@Produces("application/json")
l'uscita non è formattato in formato leggibile. Come posso farlo?
Crea questa classe ovunque nel tuo progetto. Sarà caricato sulla distribuzione. Si noti lo .configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
che configura il mapper per formattare l'output.
Per Jackson 2.0 e versioni successive, sostituire le due linee .configure()
con questi: .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
.configure(SerializationFeature.INDENT_OUTPUT, true);
e modificare le importazioni di conseguenza.
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;
}
}
Tenere presente che la formattazione ha un effetto negativo sulle prestazioni.
Solo per la cronologia, se si desidera abilitare l'output grazioso solo per alcune risorse, è possibile utilizzare the @JacksonFeatures annotation in un metodo di risorsa.
Ecco esempio:
@Produces(MediaType.APPLICATION_JSON)
@JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT })
public Bean resource() {
return new Bean();
}
'@ JacksonFeatures' è disponibile solo su un metodo, non su una classe. – NomeN
Sulla utile risposta di DaTroop, qui è un'altra versione che permette di scegliere tra JSON ottimizzata e JSON formattato in base alla presenza o meno di un parametro "bella":
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
}
}
Sebbene questa sia una buona soluzione, funziona * solo la prima volta che viene chiamata una risorsa. Dopodiché, il provider è stato registrato e sei bloccato con una bella stampa (o meno). Per una reale flessibilità, scegli una soluzione di filtro. – mvreijn
Ecco come eseguire correttamente l'output condizionale pretty/non-pretty json in base alla presenza di "pretty" nella stringa di query.
Creare un PrettyFilter
che implementa ContainerResponseFilter
, che sarà eseguito su ogni richiesta:
@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;
}
}
}
e praticamente il gioco è fatto!
È necessario assicurarsi che questa classe venga utilizzata da Jersey mediante scansione automatica dei pacchetti o registrata manualmente.
Passate poche ore a cercare di raggiungere questo obiettivo e scoprendo che nessuno ha mai pubblicato una soluzione pronta all'uso.
Questa è la soluzione migliore di gran lunga, vorrei poter upvote due volte. Non dimenticare di usare 'register (PrettyFilter.class)' nel tuo 'ResourceConfig'. – mvreijn
Se si utilizza primavera, quindi è possibile impostare globalmente la proprietà
spring.jackson.serialization.INDENT_OUTPUT=true
Maggiori informazioni presso https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
cosa JSON-serializzatore stai usando? –
Basta usare lo standard netbeans. Creato con la procedura guidata "nuovi servizi Web RESTful dalle classi di entità" Sono nuovo, ma penso che sia Jackson? – niklas
Sì, è Jackson – DaTroop