I am using the MappingJacksonJsonView in my SpringMVC application to render JSON from my controllers. I want the ObjectId from my object to render as .toString but instead it serializes the ObjectId into its parts. It works just fine in my Velocity/JSP pages:
Velocity:
$thing.id
Produces:
4f1d77bb3a13870ff0783c25
Json:
<script type="text/javascript">
$.ajax({
type: 'GET',
url: '/things/show/4f1d77bb3a13870ff0783c25',
dataType: 'json',
success : function(data) {
alert(data);
}
});
</script>
Produces:
thing: {id:{time:1327331259000, new:false, machine:974358287, timeSecond:1327331259, inc:-260555739},…}
id: {time:1327331259000, new:false, machine:974358287, timeSecond:1327331259, inc:-260555739}
inc: -260555739
machine: 974358287
new: false
time: 1327331259000
timeSecond: 1327331259
name: "Stack Overflow"
XML:
<script type="text/javascript">
$.ajax({
type: 'GET',
url: '/things/show/4f1d77bb3a13870ff0783c25',
dataType: 'xml',
success : function(data) {
alert(data);
}
});
</script>
Produces:
<com.place.model.Thing>
<id>
<__time>1327331259</__time>
<__machine>974358287</__machine>
<__inc>-260555739</__inc>
<__new>false</__new>
</id>
<name>Stack Overflow</name>
</com.place.model.Thing>
Is there a way to stop MappingJacksonJsonView from getting that much information out of the ObjectId? I just want the .toString() method, not all the details.
Thanks.
Adding the Spring config:
@Configuration
@EnableWebMvc
public class MyConfiguration {
@Bean(name = "viewResolver")
public ContentNegotiatingViewResolver viewResolver() {
ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
contentNegotiatingViewResolver.setOrder(1);
contentNegotiatingViewResolver.setFavorPathExtension(true);
contentNegotiatingViewResolver.setFavorParameter(true);
contentNegotiatingViewResolver.setIgnoreAcceptHeader(false);
Map<String, String> mediaTypes = new HashMap<String, String>();
mediaTypes.put("json", "application/x-json");
mediaTypes.put("json", "text/json");
mediaTypes.put("json", "text/x-json");
mediaTypes.put("json", "application/json");
mediaTypes.put("xml", "text/xml");
mediaTypes.put("xml", "application/xml");
contentNegotiatingViewResolver.setMediaTypes(mediaTypes);
List<View> defaultViews = new ArrayList<View>();
defaultViews.add(xmlView());
defaultViews.add(jsonView());
contentNegotiatingViewResolver.setDefaultViews(defaultViews);
return contentNegotiatingViewResolver;
}
@Bean(name = "xStreamMarshaller")
public XStreamMarshaller xStreamMarshaller() {
return new XStreamMarshaller();
}
@Bean(name = "xmlView")
public MarshallingView xmlView() {
MarshallingView marshallingView = new MarshallingView(xStreamMarshaller());
marshallingView.setContentType("application/xml");
return marshallingView;
}
@Bean(name = "jsonView")
public MappingJacksonJsonView jsonView() {
MappingJacksonJsonView mappingJacksonJsonView = new MappingJacksonJsonView();
mappingJacksonJsonView.setContentType("application/json");
return mappingJacksonJsonView;
}
}
And my controller:
@Controller
@RequestMapping(value = { "/things" })
public class ThingController {
@Autowired
private ThingRepository thingRepository;
@RequestMapping(value = { "/show/{thingId}" }, method = RequestMethod.GET)
public String show(@PathVariable ObjectId thingId, Model model) {
model.addAttribute("thing", thingRepository.findOne(thingId));
return "things/show";
}
}
By default Jackson provides the serialization of Object received. ObjectId returns the Object therefor its attributes are visible after conversion to JSON. You need to specify the type of serialization required, Here in this case it is string. Thing entity class which is used to create ThingRepository will look like this to get this done:
public class Thing {
@Id
@JsonSerialize(using= ToStringSerializer.class)
ObjectId id;
String name;
}
Here make a note of added anotation @JsonSerialize(using= ToStringSerializer.class) which instructs to serialize the ObjectID to String.
If you're using autowired instance of the auto configured mapper in Spring Boot, you can just add this customizer bean:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.serializerByType(ObjectId.class, ToStringSerializer.instance);
}
Relevant imports:
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.bson.types.ObjectId;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
And then this will reflect anywhere the autowired mapper is used, for example:
@Service
public class MyService {
private final ObjectMapper objectMapper;
private final MongoTemplate mongoTemplate;
@Autowired
public MyService(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public String getJsonForMongoCommand(Document document) {
return objectMapper.writeValueAsString(mongoTemplate.executeCommand(document));
}
}
Or in this specific case (untested, might be unnecessary):
@Bean(name = "jsonView")
public MappingJacksonJsonView jsonView(ObjectMapper objectMapper) {
final MappingJacksonJsonView mappingJacksonJsonView = new MappingJacksonJsonView();
mappingJacksonJsonView.setContentType("application/json");
mappingJacksonJsonView.setObjectMapper(objectMapper);
return mappingJacksonJsonView;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With