【问题标题】:@JsonView not propagated to ("nested") custom serializer@JsonView 未传播到(“嵌套”)自定义序列化程序
【发布时间】:2019-04-28 07:41:10
【问题描述】:

在下面的单元测试中有两个 bean:beanA 和 beanB,其中 beanA 包含对 beanB 的引用。

当序列化提供 JSON 视图的 bean 使用自定义序列化器时,beanB 的自定义序列化器不知道提供的 JSON 视图,因为测试的输出是:

{
  "clazz" : "BeanA",
  "activeView" : "ViewTest",
  "beanB" : {
    "clazz" : "BeanB",
    "activeView" : null
  }
}

我发现传播 activeView 的唯一方法是:(请参阅下面的完整源代码)

ObjectMapper mapper = (ObjectMapper) gen.getCodec();
mapper.setConfig(provider.getConfig());

但是 setConfig() 的 JavaDoc 说“只有在你知道自己在做什么的情况下才使用这个方法”——我显然不这样做......

所以我的问题是:

  1. 这种传播 JSON 视图的方式好吗?
  2. 有没有更好的办法?
  3. 谁能解释一下默认行为?

(有一些被 *** 标记的行注释掉了——这些只有在没有自定义序列化程序的情况下才有趣(在这种情况下,JSON 视图似乎被传播了))

public class ViewTest {

    @Test
    public void hello() throws JsonProcessingException {

        BeanA beanA = new BeanA();
        beanA.beanB = new BeanB();

        String result = new ObjectMapper()
//            .disable(MapperFeature.DEFAULT_VIEW_INCLUSION) // ***
            .writerWithView(ViewTest.class)
            .withDefaultPrettyPrinter()
            .writeValueAsString(beanA);

        System.out.println(result);
    }

    @JsonSerialize(using = BeanASerializer.class)
    static public class BeanA {

//        @JsonView(ViewTest.class) // ***
        public String clazz = this.getClass().getSimpleName();

//        @JsonView(ViewTest.class) // ***
        public BeanB beanB;
    }

    @JsonSerialize(using = BeanBSerializer.class)
    static public class BeanB {

//        @JsonView(ViewTest.class) // ***
        public String clazz = this.getClass().getSimpleName();
    }

    static void writeClazzAndActiveView(String clazz, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStringField("clazz", clazz);
        gen.writeFieldName("activeView");
        if (provider.getActiveView() == null) {
            gen.writeNull();
        } else {
            gen.writeString(provider.getActiveView().getSimpleName());
        }
    }

    static class BeanASerializer extends JsonSerializer<BeanA> {

        @Override
        public void serialize(BeanA bean, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {

            gen.writeStartObject();
            writeClazzAndActiveView(bean.clazz, gen, provider);

            // the only way I found to propagate the activeView:
//            ObjectMapper mapper = (ObjectMapper) gen.getCodec();
//            mapper.setConfig(provider.getConfig());

            gen.writeObjectField("beanB", bean.beanB);
            gen.writeEndObject();
        }
    }

    static class BeanBSerializer extends JsonSerializer<BeanB> {

        @Override
        public void serialize(BeanB bean, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {

            gen.writeStartObject();
            writeClazzAndActiveView(bean.clazz, gen, provider);
            gen.writeEndObject();
        }
    }
}

【问题讨论】:

标签: java spring jackson json-view


【解决方案1】:

Active 应该通过SerializerProvider 正确传播。你是对的,你不应该这样设置(也不必设置)视图——一方面,它不是线程安全的,ObjectMapper 的所有配置都必须在任何和所有使用之前完成 (ObjectReader 和 ObjectWriter 允许通过各种工厂方法进行每次调用更改)。

为什么会发生这种情况尚不清楚:我认为提交带有版本信息和完整复制(如果它比代码更多)的错误是有意义的。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
  • 1970-01-01
  • 2018-10-06
  • 2012-05-08
相关资源
最近更新 更多