@JsonView 未传播到 ("nested") 自定义序列化程序
@JsonView not propagated to ("nested") custom serializer
在下面的单元测试中有两个 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 说 "only use this method if you know what you are doing" - 我显然不这样做...
所以我的问题是:
- 这种传播JSON视图的方式可以吗?
- 有没有更好的方法?
- 有人可以解释默认行为吗?
(有些行被 *** 标记为注释 - 这些只有在没有自定义序列化程序的情况下才有趣(在这种情况下 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();
}
}
}
Active 应该通过 SerializerProvider
正确传播。你是对的,你不应该(也不必设置)那样设置视图——它不是线程安全的,一方面, ObjectMapper
的所有配置都应该在任何和所有使用之前完成
(ObjectReader
和 ObjectWriter
允许通过各种工厂方法更改每次调用)。
发生这种情况的原因尚不清楚:我认为用版本信息和完整复制(如果除了代码之外还有更多信息)提交错误是有意义的。
在下面的单元测试中有两个 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 说 "only use this method if you know what you are doing" - 我显然不这样做...
所以我的问题是:
- 这种传播JSON视图的方式可以吗?
- 有没有更好的方法?
- 有人可以解释默认行为吗?
(有些行被 *** 标记为注释 - 这些只有在没有自定义序列化程序的情况下才有趣(在这种情况下 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();
}
}
}
Active 应该通过 SerializerProvider
正确传播。你是对的,你不应该(也不必设置)那样设置视图——它不是线程安全的,一方面, ObjectMapper
的所有配置都应该在任何和所有使用之前完成
(ObjectReader
和 ObjectWriter
允许通过各种工厂方法更改每次调用)。
发生这种情况的原因尚不清楚:我认为用版本信息和完整复制(如果除了代码之外还有更多信息)提交错误是有意义的。