16

在 Java 中,当我使用

@Produces("application/json")

注释输出未格式化为人类可读的形式。我如何做到这一点?

4

7 回答 7

24

仅作记录,如果您只想为某些资源启用漂亮的输出,您可以在资源方法上使用@JacksonFeatures 注释。

这是示例:

@Produces(MediaType.APPLICATION_JSON)
@JacksonFeatures(serializationEnable =  { SerializationFeature.INDENT_OUTPUT })
public Bean resource() {
    return new Bean();
}
于 2014-08-21T08:35:49.160 回答
17

这就是您如何根据查询字符串中“漂亮”的存在正确地进行条件漂亮/非漂亮 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;
        }
    }
}

差不多就是这样!

您需要确保 Jersey 通过自动包扫描或手动注册来使用此类。

花了几个小时试图实现这一目标,发现之前没有人发布过现成的解决方案。

于 2015-09-18T10:16:59.923 回答
16

在项目中的任何位置创建此类。它将在部署时加载。注意.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;
    }
}

请记住,格式化会对性能产生负面影响。

于 2012-05-10T13:08:27.603 回答
3

如果您使用的是 Spring,那么您可以全局设置属性

spring.jackson.serialization.INDENT_OUTPUT=true

更多信息在https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html

于 2017-02-28T23:10:48.963 回答
2

基于有用的 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
    }
}
于 2015-04-23T14:11:26.320 回答
1

如果您使用的是jersey-media-json-binding使用 Yasson(JSR-367 的官方 RI)和 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;
    }
}
于 2019-08-30T08:26:57.720 回答
0

Jersey 1.x 的替代方案:

org.codehaus.jackson.map.ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
于 2021-06-25T23:35:38.977 回答