Java Jackson提供程序同一类的多个ObjectMapper

Java Jackson提供程序同一类的多个ObjectMapper,java,json,serialization,jackson,jackson-modules,Java,Json,Serialization,Jackson,Jackson Modules,我想用不同资源方法中的两个映射器序列化同一类别类。 我已经编写了两个类,它们以两种不同的方式序列化了这个类别 分类序列化和分类再序列化 public class MyJacksonJsonProvider implements ContextResolver<ObjectMapper> { private static final ObjectMapper MAPPER = new ObjectMapper(); static { MAPPER.en

我想用不同资源方法中的两个映射器序列化同一类别类。
我已经编写了两个类,它们以两种不同的方式序列化了这个类别 分类序列化分类再序列化

public class MyJacksonJsonProvider implements ContextResolver<ObjectMapper>
{
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        MAPPER.enable(SerializationFeature.INDENT_OUTPUT);          
        MAPPER.registerModule(new SimpleModule()
                .addSerializer(Category.class, new CategorySerializer(Category.class)));  
        }

    public MyJacksonJsonProvider() {
        System.out.println("Instantiate MyJacksonJsonProvider");
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        System.out.println("MyJacksonProvider.getContext() called with type: "+type);
        return MAPPER;
    }
类别重新序列化扩展StdSerializer已在资源中注册

ContextResolver<ObjectMapper> cr = providers
                    .getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);
            ObjectMapper c = cr.getContext(ObjectMapper.class);
            c.registerModule(new SimpleModule()
                    .addSerializer(Category.class, new CategoryTreeSerializer(Category.class)));
ContextResolver cr=提供程序
.getContextResolver(ObjectMapper.class、MediaType.APPLICATION\u JSON\u类型);
ObjectMapper c=cr.getContext(ObjectMapper.class);
c、 registerModule(新的SimpleModule()
.addSerializer(Category.class,新CategoryTreeSerializer(Category.class));
不幸的是,这不起作用,因为映射器是静态的final。
调用的第一个资源,注册模块,然后不更改

例如,如果我首先调用/categoriestree资源,我将得到CategoryTreeSerialized序列化。
但是如果在调用/categories之后,资源总是使用CategoryTreeSerialized类序列化,而不是使用CategorySerialized类序列化


(反之亦然)

不确定这是否是SpringMVC,我的例子是JAX-RS,但通过谷歌搜索,您应该可以找到类似的解决方案。 您可以为每个
请求
返回一个
响应
,其中正文使用相应的序列化程序序列化,如:

@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categories")
public Response getCategories(){
    List<Category> categories = categoryService.findAll();
    ResponseBuilder response = ResponseBuilder.ok()
            .entity(new MyCategoriesMapper()
                .build(categories))
            .type(MediaType.APPLICATION_JSON));

    return response.build();
}

@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categoriestree")
public Response getCategoriesTree(){
    List<Category> categories = categoryService.findAll();
    ResponseBuilder response = ResponseBuilder.ok()
            .entity(new MyCategoriesTreeMapper()
                .build(categories))
            .type(MediaType.APPLICATION_JSON));

    return response.build();
}
@GET
@产生(value=MediaType.APPLICATION_JSON+“charset=“+CharEncoding.UTF_8”)
@路径(“/类别”)
公众回应{
List categories=categoryService.findAll();
ResponseBuilder response=ResponseBuilder.ok()
.entity(新MyCategoriesMapper()
.建造(类别))
.type(MediaType.APPLICATION_JSON));
返回response.build();
}
@得到
@产生(value=MediaType.APPLICATION_JSON+“charset=“+CharEncoding.UTF_8”)
@路径(“/categoriestree”)
公共响应getCategoriesTree(){
List categories=categoryService.findAll();
ResponseBuilder response=ResponseBuilder.ok()
.entity(新的MyCategoriesTreeMapper()
.建造(类别))
.type(MediaType.APPLICATION_JSON));
返回response.build();
}

我找到的唯一解决方案是创建一个包装类,该类复制Category类并注册模块

我已经创建了一个名为CategoryTree的Category实体副本,它是实体的精确副本 我使用CategoryTreeSerialized序列化注册了CategoryTree模块

@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyJacksonJsonProvider implements ContextResolver<ObjectMapper>
{
    private static final ObjectMapper MAPPER_DEFAULT = new ObjectMapper();


    static {
       MAPPER_DEFAULT.enable(SerializationFeature.INDENT_OUTPUT);
       MAPPER_DEFAULT.registerModule(new SimpleModule()
            .addSerializer(Category.class, new CategorySerializer(Category.class)));
       MAPPER_DEFAULT.registerModule(new SimpleModule()
            .addSerializer(CategoryTree.class, new CategoryTreeSerializer(CategoryTree.class)));

    public MyJacksonJsonProvider() {
        System.out.println("Instantiate MyJacksonJsonProvider");
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        System.out.println("MyJacksonProvider.getContext() called with 
        return MAPPER_DEFAULT;
    }
}
@Provider
@产生(MediaType.APPLICATION_JSON)
@使用(MediaType.APPLICATION_JSON)
公共类MyJacksonJsonProvider实现ContextResolver
{
私有静态最终ObjectMapper映射器_默认值=新ObjectMapper();
静止的{
MAPPER_DEFAULT.enable(SerializationFeature.INDENT_输出);
MAPPER_DEFAULT.registerModule(新的SimpleModule()
.addSerializer(Category.class,新的CategorySerializer(Category.class));
MAPPER_DEFAULT.registerModule(新的SimpleModule()
.addSerializer(CategoryTree.class,新的CategoryTree序列化程序(CategoryTree.class));
公共MyJacksonJsonProvider(){
System.out.println(“实例化MyJacksonJsonProvider”);
}
@凌驾
公共对象映射器getContext(类类型){
System.out.println(“使用
返回MAPPER_默认值;
}
}
在CategoryResource类中,我得到一个列表的副本,该列表转换为List

@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categoriestree")
public List getCategoriesTree(){
    List<Category> categories = categoryService.findAll();

    List<CategoryTree> categoryTrees =
            new CategoryTree().createList(categories);
    return categoryTrees;
}
@GET
@产生(value=MediaType.APPLICATION_JSON+“charset=“+CharEncoding.UTF_8”)
@路径(“/categoriestree”)
公共列表getCategoriesTree(){
List categories=categoryService.findAll();
列表类别树=
新建CategoryTree().createList(类别);
返回类别树;
}
那么CategoryTree就是Category的副本
此解决方案性能不高,也不优雅,但它是唯一有效的解决方案,因为无法注销模块


如果有人有一个不同的、高性能的、优雅的解决方案,写下来是有意义的。你的问题是什么?当我调用getCategories(/categories)时,我希望用CategorySerialized实现序列化,当我调用GetCategoryStree(/categoriestree)时我使用CategoryTreeSerializedSo进行序列化,以便使用不同的映射器。如何?在同一个提供程序中?但是,无论在何处。我不知道问题出在哪里。
@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categories")
public Response getCategories(){
    List<Category> categories = categoryService.findAll();
    ResponseBuilder response = ResponseBuilder.ok()
            .entity(new MyCategoriesMapper()
                .build(categories))
            .type(MediaType.APPLICATION_JSON));

    return response.build();
}

@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categoriestree")
public Response getCategoriesTree(){
    List<Category> categories = categoryService.findAll();
    ResponseBuilder response = ResponseBuilder.ok()
            .entity(new MyCategoriesTreeMapper()
                .build(categories))
            .type(MediaType.APPLICATION_JSON));

    return response.build();
}
@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyJacksonJsonProvider implements ContextResolver<ObjectMapper>
{
    private static final ObjectMapper MAPPER_DEFAULT = new ObjectMapper();


    static {
       MAPPER_DEFAULT.enable(SerializationFeature.INDENT_OUTPUT);
       MAPPER_DEFAULT.registerModule(new SimpleModule()
            .addSerializer(Category.class, new CategorySerializer(Category.class)));
       MAPPER_DEFAULT.registerModule(new SimpleModule()
            .addSerializer(CategoryTree.class, new CategoryTreeSerializer(CategoryTree.class)));

    public MyJacksonJsonProvider() {
        System.out.println("Instantiate MyJacksonJsonProvider");
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        System.out.println("MyJacksonProvider.getContext() called with 
        return MAPPER_DEFAULT;
    }
}
@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categoriestree")
public List getCategoriesTree(){
    List<Category> categories = categoryService.findAll();

    List<CategoryTree> categoryTrees =
            new CategoryTree().createList(categories);
    return categoryTrees;
}