当前位置: 首页 > 知识库问答 >
问题:

在生成的JSON末尾添加新行

阮梓
2023-03-14

我有一个基于泽西(1. x)的REST服务。它使用Jackson 2.4.4生成JSON响应。我需要在响应的末尾添加一个换行符(cURL用户抱怨响应中没有新行)。我使用泽西漂亮打印功能(SeriazationFeature.INDENT_OUTPUT)。

当前:{\n“prop”:“value”\n}

通缉:{\n“prop”:“value”\n}\n

>

  • 我尝试使用自定义序列化程序。我只需要在根对象的末尾添加\n。序列化器是按数据类型定义的,这意味着,如果此类类的实例嵌套在响应中,我将在JSON的中间获得\n

    我想到了子类化com.fasterxml.jackson.core.JsonGenerator.java,覆盖关闭(),在其中我将添加WriteRaw('\n'),但这感觉非常hacky。

    另一个想法是添加Servlet过滤器,这将重写泽西过滤器的响应,添加\n并将内容Lenght增加1。看起来不仅俗气,而且效率低下。

    我也可以放弃处理序列化内容的工作,而使用ObjectMapper。writeValue()“\n”,但这对我的代码来说是相当麻烦的(需要更改很多地方)。

    这个问题的干净解决方案是什么?

    我发现这些线程用于相同的问题,但没有一个提供解决方案:

    • http://markmail.org/message/nj4aqheqobmt4o5c
    • http://jackson-users.ning.com/forum/topics/add-newline-after-object-serialization-in-jersey

    最新消息

    最后,我选择了@arachnid的解决方案,使用了NewlineAddingPrettyPrinter(也是2.6.2版本)。遗憾的是,Jaskson作为JAX-RSJSON提供程序时,它无法开箱即用。在ObjectMapper中更改的PrettyPrinter不会传播到JsonGenerator(请参见此处原因)。为了让它工作,我必须添加ResponseFilter,它添加了ObjectWriterModifier(现在我可以根据输入参数轻松地在pretty print和minimal之间切换):

    @Provider
    public class PrettyPrintFilter extends BaseResponseFilter {
    
        public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
            ObjectWriterInjector.set(new PrettyPrintToggler(true));
            return response;
        }
    
        final class PrettyPrintToggler extends ObjectWriterModifier {
    
            private static final PrettyPrinter NO_PRETTY_PRINT = new MinimalPrettyPrinter();
    
            private final boolean usePrettyPrint;
    
            public PrettyPrintToggler(boolean usePrettyPrint) {
                this.usePrettyPrint = usePrettyPrint;
            }
    
            @Override
            public ObjectWriter modify(EndpointConfigBase<?> endpoint, MultivaluedMap<String, Object> responseHeaders,
                                       Object valueToWrite, ObjectWriter w, JsonGenerator g) throws IOException {
                if (usePrettyPrint) g.setPrettyPrinter(new NewlineAddingPrettyPrinter());
                else g.setPrettyPrinter(NO_PRETTY_PRINT);
                return w;
            }
    
        }
    }
    
  • 共有2个答案

    詹唯
    2023-03-14

    尚未测试,但以下各项应有效:

    public class MyObjectMapper extends ObjectMapper {
    
           _defaultPrettyPrinter = com.fasterxml.jackson.core.util.MinimalPrettyPrinter("\n");
    
        // AND/OR
    
           @Override
           protected PrettyPrinter _defaultPrettyPrinter() {
                return new com.fasterxml.jackson.core.util.MinimalPrettyPrinter("\n");
           }
    
    }
    
    
    public class JerseyConfiguration extends ResourceConfig {
        ...
        MyObjectMapper mapper = new MyObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT); //enables pretty printing
    
        // create JsonProvider to provide custom ObjectMapper
        JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
        provider.setMapper(mapper);
        register(provider); //register so that jersey use it
    }
    

    不知道这是否是“最干净”的解决方案,但感觉没有其他解决方案那么粗糙。

    应该产生类似于

    {\n“根”:“1”\n}\n{\n“根2”:“2”\n}

    但是,如果只有一个根元素,这似乎不起作用。

    想法来自https://gist.github.com/deverton/7743979

    平和雅
    2023-03-14

    实际上,包装(而不是子类化)JsonGenerator并不是很糟糕:

    public static final class NewlineAddingJsonFactory extends JsonFactory {
        @Override
        protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException {
            return new NewlineAddingJsonGenerator(super._createGenerator(out, ctxt));
        }
    
        @Override
        protected JsonGenerator _createUTF8Generator(OutputStream out, IOContext ctxt) throws IOException {
            return new NewlineAddingJsonGenerator(super._createUTF8Generator(out, ctxt));
        }
    }
    
    public static final class NewlineAddingJsonGenerator extends JsonGenerator {
        private final JsonGenerator underlying;
        private int depth = 0;
    
        public NewlineAddingJsonGenerator(JsonGenerator underlying) {
            this.underlying = underlying;
        }
    
        @Override
        public void writeStartObject() throws IOException {
            underlying.writeStartObject();
            ++depth;
        }
    
        @Override
        public void writeEndObject() throws IOException {
            underlying.writeEndObject();
            if (--depth == 0) {
                underlying.writeRaw('\n');
            }
        }
    
        // ... and delegate all the other methods of JsonGenerator (CGLIB can hide this if you put in some time)
    }
    
    
    @Test
    public void append_newline_after_end_of_json() throws Exception {
        ObjectWriter writer = new ObjectMapper(new NewlineAddingJsonFactory()).writer();
        assertThat(writer.writeValueAsString(ImmutableMap.of()), equalTo("{}\n"));
        assertThat(writer.writeValueAsString(ImmutableMap.of("foo", "bar")), equalTo("{\"foo\":\"bar\"}\n"));
    }
    

    servlet过滤器也不一定太糟糕,尽管最近ServletOutputStream接口已经更多地参与到正确拦截中。

    我发现通过PrettyPrinter进行此操作在早期的Jackson版本(如2.4.4)上存在问题,部分原因是需要通过ObjectWriter进行正确配置:仅在Jackson 2.6中修复。为完整起见,这是一个有效的2.5解决方案:

    @Test
    public void append_newline_after_end_of_json() throws Exception {
        // Jackson 2.6:
    //      ObjectMapper mapper = new ObjectMapper()
    //              .setDefaultPrettyPrinter(new NewlineAddingPrettyPrinter())
    //              .enable(SerializationFeature.INDENT_OUTPUT);
    //      ObjectWriter writer = mapper.writer();
    
        ObjectMapper mapper = new ObjectMapper();
        ObjectWriter writer = mapper.writer().with(new NewlineAddingPrettyPrinter());
        assertThat(writer.writeValueAsString(ImmutableMap.of()), equalTo("{}\n"));
        assertThat(writer.writeValueAsString(ImmutableMap.of("foo", "bar")),
                equalTo("{\"foo\":\"bar\"}\n"));
    }
    
    public static final class NewlineAddingPrettyPrinter
                        extends MinimalPrettyPrinter
                        implements Instantiatable<PrettyPrinter> {
        private int depth = 0;
    
        @Override
        public void writeStartObject(JsonGenerator jg) throws IOException, JsonGenerationException {
            super.writeStartObject(jg);
            ++depth;
        }
    
        @Override
        public void writeEndObject(JsonGenerator jg, int nrOfEntries) throws IOException, JsonGenerationException {
            super.writeEndObject(jg, nrOfEntries);
            if (--depth == 0) {
                jg.writeRaw('\n');
            }
        }
    
        @Override
        public PrettyPrinter createInstance() {
            return new NewlineAddingPrettyPrinter();
        }
    }
    
     类似资料:
    • 问题内容: 我有一个文本区域,其中包含一些文本,我想再次向其中添加一些行(第一行+我要添加的其他行),但是它不起作用。 我现在的操作方式将擦除旧文本并仅显示新行。 问题答案: 代替使用,使用。 将给定的文本追加到文档末尾。如果模型为null或字符串为null或为空,则不执行任何操作。 这会将文字添加到您的末尾。 另一个选择是使用来从中获取文本,然后操作String(添加或删除或更改String),

    • 注意,这个空间只在最末端可见,因为我不想改变布局。我可以使recycerview有一个50dp的边际底部,但我不想这样做。

    • 我正在使用Goland来编写我的grpc应用程序。生成我的原型文件后,文件末尾不存在尾随换行符。有没有办法在 IDE 中启用此功能?

    • 我有一个<代码> 并且当用户将他们的文本粘贴到textarea字段时。 洛雷姆·伊普苏姆·多洛尔·西特(Lorem ipsum dolor sit amet), 连续的发展精英们, 我们的目标是实现平等。 单击按钮时,它将如下所示。 Lorem ipsum dolor sit amet,<代码> 帮帮我伙计们。

    • 我想知道如何在数组末尾添加或追加一个新元素。有什么简单的方法可以在末尾添加元素吗?我知道如何使用StringBuffer,但我不知道如何使用它在数组中添加元素。我更喜欢没有ArrayList或List。我想知道StringBuffer是否能处理整数。

    • 下面是我的节点类 下面是我的带有插入方法的链表类 我得到以下结果, 端部插入20 正在打印节点1-->10-->5-->none->NULL