杰克逊提供程序同一类的多个ObjectMapper
问题描述:
我想序列化与两个映射器在不同的资源方法相同的类别类。
我写了两种不同的方式 CategorySerialized和CategoryTreeSerialized杰克逊提供程序同一类的多个ObjectMapper
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延伸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)));
内不幸的是,这并不工作,因为映射是静态的决赛。
所谓的第一资源,注册模块,然后不改变
例如,如果我称之为/categoriestree资源第一,我得到CategoryTreeSerialized系列化。
但是,如果以后我叫/类别资源总是与CategoryTreeSerialized类序列化,而不是与CategorySerialized
(反之亦然)
答
不知道这可能是Spring MVC的,我的例子适用于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();
}
答
我发现的唯一的解决方案是创建一个包装类,使范畴类的副本和: 你可以为每个Request
,在身体与相应的串行连载中一样返回Response
注册
我已经创建了一个名为CategoryTree类别实体的副本是实体 的精确副本,我注册了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类,我得到转化为列出清单副本
@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是
类别 副本这个解决方案不是很表演和优雅,但它是唯一一个作品,因为它无法注销模块
如果有人有不同,表演和优雅的解决方案写下来
有道理。你有什么问题? – shmosel
我想,当我打电话** getCategories **(/类别)我得到序列化** CategorySerialized **,当我打电话** getCategoryTree **(/ categoriestree)我得到序列化** CategoryTreeSerialized ** – Pako
所以使用不同的映射器。 – shmosel