覆盖JacksonJsonProvider.writeTo时,是否可以指定用于序列化的视图?

时间:2014-01-21 08:45:24

标签: java annotations jackson

我有Resteasy-3.0.6,Jackson-2.2.3和CDI(在Wildfly-8.0.0.CR1上运行)的设置。在我的例子中,每个实体都有一个混合类,它扩展了它并指定了要序列化的属性。有两个“视图”,我们称之为 Basic Extended 。由于我需要的对象的哪种视图取决于序列化的“根”对象,因此这些视图需要是每个对象。所以我重新使用混合类。例如:

public class Job { 
    @Id private Long id;
    @OneToMany(mappedBy="job") private Set<Bonus> bonuses;
}

public class Bonus {
    @Id private Long id;
    @ManyToOne(optional=false) private Job job;
    private BigDecimal value;
}

public abstract class JsonJob extends Job { 
    abstract Long getId();

    @JsonView({ JsonJob.class })
    abstract Set<Bonus> getBonuses();
}

public abstract class JsonBonus extends Bonus {
    abstract BigDecimal getValue();
}

现在我正在寻找一种方法来挂钩杰克逊的序列化过程,如果根实体是JsonJob,则将Job指定为视图。我目前正在使用JacksonJsonProvider#writeTo

@Override
public void writeTo(Object value, Class<?> type, Type genericType, 
                    Annotation[] annotations, MediaType mediaType, 
                    MultivaluedMap<String, Object> httpHeaders, 
                    OutputStream entityStream) throws IOException {
    Class view = getViewForType(type); // if no mix-in class is set, return Object
    ObjectMapper mapper = locateMapper(type, mediaType);

    // require all properties to be explicitly specified for serialization
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
    mapper.registerModule(new SerializationMixinConf()); // registers all mix-ins

    super.writeTo(value, type, genericType, annotations, mediaType, 
        httpHeaders, entityStream);
}

关键是:这是有效的, iff 调用方法是注释@JsonView但是由于这个主要用户是一个通用的超类,我不能直接在方法中添加注释。有人可以建议一种方法来设置现有映射器中的视图(setSerializationConfig()似乎在jackson-2中消失)或动态地将@JsonView添加到annotations数组?

2 个答案:

答案 0 :(得分:0)

以下是writeTo现在的内容:

ObjectMapper mapper = locateMapper(type, mediaType);
// require all properties to be explicitly specified for serialization
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
mapper.registerModule(new SerializationMixinConf());

// TODO: check if we already have @JsonView
Annotation[] myAnnotations = Arrays.copyOf(annotations, annotations.length + 1);
myAnnotations[annotations.length] = new JsonViewQualifier(view);

super.writeTo(value, type, genericType, myAnnotations, mediaType, 
    httpHeaders, entityStream);

限定符只是从AnnotationLiteral延伸:

public class JsonViewQualifier extends AnnotationLiteral<JsonView> 
        implements JsonView {
    private final Class[] views;

    public JsonViewQualifier(Class[] views) { this.views = views; }
    public JsonViewQualifier(Class view) { this(new Class[] { view }); }

    @Override
    public Class<?>[] value() {
        return views;
    }
}

请注意,这将为每个视图生成 new 编写器(应该如此)。

答案 1 :(得分:0)

使用Jackson 2.3,您可以在JAX-RS端点上使用@JsonView,如果这样做有帮助的话。

但如果没有,另一种可能性就是直接使用ObjectWriter(编写者是从ObjectMapper创建的),用特定的视图构建编写器。这是完全动态的,可以在每次通话的基础上完成。这需要绕过JAX-RS逻辑,通常你需要返回StreamingOutput(而不是实际的POJO),但这是最终的可配置性。