我有一个Spring MVC应用程序,它要求我将特定实体列表的id和名称转换为具有特定格式的JSON对象数组,并在特定请求中输出。也就是说,我需要一个像这样的JSON对象数组:
{
label: Subject.getId()
value: Subject.getName()
}
使用jQuery Autocomplete插件轻松使用。
所以在我的控制器中,我写了以下内容:
@RequestMapping(value = "/autocomplete.json", method = RequestMethod.GET)
@JsonSerialize(contentUsing=SubjectAutocompleteSerializer.class)
public @ResponseBody List<Subject> autocompleteJson() {
return Subject.findAllSubjects();
}
// Internal class
public class SubjectAutocompleteSerializer extends JsonSerializer<Subject> {
@Override
public void serialize(Subject value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("label", value.getId().toString());
jgen.writeStringField("value", value.getName());
jgen.writeEndObject();
}
}
然而,我回来的JSON是Jackson推断的默认序列化。我的自定义序列化程序似乎完全被忽略了。显然问题是@JsonSerialize或JsonSerializer的使用不正确,但我无法在任何地方找到这些内容的正确用法。
使用Jackson实现我想要的序列化的正确方法是什么?请注意,在此上下文中以这种方式仅序列化实体非常重要,并且在其他位置打开其他序列化
答案 0 :(得分:8)
@JsonSerialize应该在被序列化的类而不是控制器上设置。
答案 1 :(得分:0)
@JsonSerialize应该在要序列化的类而不是控制器上设置。
我想在上述答案中加上我的2美分(一个用例示例)...您不能总是为特定类型指定json序列化器,特别是在这是通用类型的情况下(确保不会允许在运行时为特定的泛型选择序列化程序),但是您始终可以创建一个新类型(您可以扩展广义类型,或者如果序列化类型是final且不能扩展,则可以创建包装器),并为这种类型。例如,您可以执行以下操作来序列化不同的org.springframework.data.domain.Page类型:
@JsonComponent
public class PageOfMyDtosSerializer
extends JsonSerializer<Page<MyDto>> {
@Override
public void serialize(Page<MyDto> page,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)
throws IOException {
//...serialization logic for Page<MyDto> type
}
}
@JsonSerialize(using = PageOfMyDtosSerializer.class)
public class PageOfMyDtos extends PageImpl<MyDto> {
public PageOfMyDtos(List<MyDto> content, Pageable pageable, long total) {
super(content, pageable, total);
}
}
然后您可以从服务的方法中返回您的类型-明确使用必要的序列化器:
@Service
@Transactional
public class MyServiceImpl implements MyService {
...
@Override
public Page<UserProfileDto> searchForUsers(
Pageable pageable,
SearchCriteriaDto criteriaDto) {
//...some business logic
/*here you pass the necessary search Specification or something else...*/
final Page<Entity> entities = myEntityRepository.findAll(...);
/*here you goes the conversion logic of your choice...*/
final List<MyDto> content = modelMapper.map(entieis.getContent(), new TypeToken<List<MyDto>>(){}.getType());
/*and finally return your the your new type so it will be serialized with the jsonSerializer we have specified*/
return new PageOfMyDtos(content, pageable, entities.getTotalElements());
}
}