我想用不同的资源方法用两个mapper序列化相同的Category类 我写过两个以两种不同方式序列化Category的类 CategorySerialized 和 CategoryTreeSerialized
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;
}
这是简单的实体类别
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Type(type = "objectid")
private String id;
private String name;
@ManyToOne
@JsonManagedReference
private Category parent;
@JsonBackReference
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
@Column(insertable = false)
private List<Category> children;
....getter and setter ....
}
这是CategoryResource
@Path(value = "resource")
public class CategoryResource {
@Inject
CategoryService categoryService;
@Context
Providers providers;
@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categories")
public List getCategories(){
List<Category> categories = categoryService.findAll();
return categories;
}
@GET
@Produces(value = MediaType.APPLICATION_JSON+";charset="+ CharEncoding.UTF_8)
@Path("/categoriestree")
public List getCategoriesTree(){
List<Category> categories = categoryService.findAll();
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)));
return categories;
}
CategorySerialized extends StdSerializer已向提供商
注册MAPPER.registerModule(new SimpleModule()
.addSerializer(Category.class, new CategorySerializer(Category.class)));
CategoryTreeSerialized 扩展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)));
不幸的是,这不起作用,因为mapper是静态的final 调用第一个资源,注册模块然后不更改
例如,如果我先调用 / categoriestree 资源,我会获得CategoryTreeSerialized序列化。
但是,如果在我调用 / categories 之后,资源总是使用CategoryTreeSerialized类序列化而不是使用CategorySerialized
(反之亦然)
答案 0 :(得分:1)
不确定这可能是Spring MVC,我的例子是JAX-RS,但是使用Google搜索你应该找到类似的解决方案。
您可以为每个Response
返回一个Request
,其中正文与相应的序列化程序序列化,如:
@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();
}
答案 1 :(得分:0)
我找到的唯一解决方案是创建一个包装类,它创建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;
}
}
在CategoryResource类中,我得到一个List转换为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;
}
然后CategoryTree是类别
的副本
这个解决方案性能不是很优雅,但它是唯一可行的解决方案,因为无法取消注册模块
如果某人有不同的,表现优雅的解决方案,请将其写下来