Подтвердить что ты не робот

Jax-rs json довольно выход

в Java, когда я использую

@Produces("application/json")

аннотация, выход не формируется в читаемую человеком форму. Как это сделать?

4b9b3361

Ответ 1

Для справки: если вы хотите включить симпатичный вывод только для некоторых ресурсов, вы можете использовать аннотацию @JacksonFeatures для метода ресурса.

Вот пример:

@Produces(MediaType.APPLICATION_JSON)
@JacksonFeatures(serializationEnable =  { SerializationFeature.INDENT_OUTPUT })
public Bean resource() {
    return new Bean();
}

Ответ 2

Создайте этот класс в любом месте вашего проекта. Он будет загружен при развертывании. Обратите внимание на .configure(SerializationConfig.Feature.INDENT_OUTPUT, true);, который настраивает преобразователь для форматирования вывода.

Для Jackson 2.0 и более поздних версий замените две строки .configure() на следующие:   .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)  .configure(SerializationFeature.INDENT_OUTPUT, true);

И измените свой импорт соответственно.

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;
    }
}

Имейте в виду, что форматирование отрицательно влияет на производительность.

Ответ 3

Вот как вы можете правильно сделать условный симпатичный/некрасивый json-вывод, основанный на наличии "симпатичного" в строке запроса.

Создайте PrettyFilter, который реализует ContainerResponseFilter, который будет выполняться в каждом запросе:

@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;
        }
    }
}

И в значительной степени это!

Вам нужно будет убедиться, что этот класс будет использоваться Джерси либо автоматическим сканированием пакетов, либо зарегистрирован вручную.

Прошло несколько часов, пытаясь добиться этого, и обнаружил, что никто не опубликовал готовое к использованию решение раньше.

Ответ 4

Основываясь на полезном ответе DaTroop, вот еще одна версия, которая позволяет выбирать между оптимизированным json и форматированным json на основе отсутствия или наличия "симпатичного" параметра:

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

Ответ 6

Если вы используете зависимость jersey-media-json-binding, в которой используются Yasson (официальный RI JSR-367) и JAVAX-JSON, вы можете ввести красивую печать следующим образом:

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class RandomConfig implements ContextResolver<Jsonb> {
    private final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true));

    public RandomConfig() { }

    @Override
    public Jsonb getContext(Class<?> objectType) {
        return jsonb;
    }
}