gpt4 book ai didi

json - 在 Jersey 生成的 JSON 末尾添加新行

转载 作者:行者123 更新时间:2023-12-01 15:40:45 25 4
gpt4 key购买 nike

我有一个基于 Jersey (1.x) 的 REST 服务。它使用 Jackson 2.4.4 生成 JSON 响应。我需要在响应末尾添加一个换行符(cURL 用户提示响应中没有换行符)。我正在使用 Jersey pretty-print 功能( SerializationFeature.INDENT_OUTPUT )。

当前:{\n "prop" : "value"\n}
通缉:{\n "prop" : "value"\n}\n

  • 我尝试使用自定义序列化程序。我需要添加 \n仅在根对象的末尾。序列化程序是按数据类型定义的,这意味着,如果此类类的实例嵌套在响应中,我将得到 \n在我的 JSON 中间。
  • 我想到了子类 com.fasterxml.jackson.core.JsonGenerator.java , 覆盖 close()我要添加 writeRaw('\n') ,但这感觉很hacky。
  • 另一个想法是添加 Servlet 过滤器,它会重写来自 Jersey 过滤器的响应,添加 \n并将 contentLenght 增加 1。看起来不仅笨拙,而且效率低下。
  • 我也可以放弃 Jersey 来处理内容序列化并做 ObjectMapper.writeValue() + "\n" ,但这对我的代码非常有干扰(需要更改很多地方)。

  • 该问题的干净解决方案是什么?

    我发现这些线程解决了同样的问题,但没有一个提供解决方案:
  • http://markmail.org/message/nj4aqheqobmt4o5c
  • http://jackson-users.ning.com/forum/topics/add-newline-after-object-serialization-in-jersey


  • 更新

    最后我用 NewlineAddingPrettyPrinter 寻求@arachnid 的解决方案。 (也是 2.6.2 的保险杠 jackson 版本)。可悲的是,它不适用于 Jaskson 作为 JAX-RS 的开箱即用。 Json 提供者。已更改 PrettyPrinterObjectMapper不会传播到 JsonGenerator (见 here 为什么)。为了使它工作,我必须添加 ResponseFilter其中增加了 ObjectWriterModifier (现在我可以根据输入参数轻松地在 pretty-print 和最小打印之间切换):
    @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;
    }

    }
    }

    最佳答案

    实际上,包装(不是子类化) 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 接口(interface)更多地涉及正确拦截。

    我发现在早期的 Jackson 版本(例如您的 2.4.4)上通过 PrettyPrinter 执行此操作有问题,部分原因是需要通过 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();
    }
    }

    关于json - 在 Jersey 生成的 JSON 末尾添加新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33040791/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com