Java spring MappingJacksonJsonView not doing toString on mongodb ObjectId

I am using MappingJacksonJsonView in my SpringMVC application to render JSON from my controllers. I want the ObjectId from my object to display as .toString, but instead it serializes the ObjectId in its part. It works great on 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 such information from ObjectId? I just need the .toString () method, not all the details.

Thanks.

Adding Spring configuration:

 @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"; } } 
+4
source share
2 answers

The previous answer did the trick, but it was ugly and not very thought out - a clear workaround to solve this problem.

The real problem is that the ObjectId deserialized into its constituent parts. MappingJacksonJsonView sees an ObjectId for what it is, an object and goes to work on it. The deserialized fields visible in JSON are the fields that make up the ObjectId . To stop the serialization / deserialization of such an object, you need to configure CustomObjectMapper , which extends ObjectMapper .

Here is the CustomeObjectMapper :

 public class CustomObjectMapper extends ObjectMapper { public CustomObjectMapper() { CustomSerializerFactory sf = new CustomSerializerFactory(); sf.addSpecificMapping(ObjectId.class, new ObjectIdSerializer()); this.setSerializerFactory(sf); } } 

Here is the ObjectIdSerializer that uses CustomObjectMapper :

 public class ObjectIdSerializer extends SerializerBase<ObjectId> { protected ObjectIdSerializer(Class<ObjectId> t) { super(t); } public ObjectIdSerializer() { this(ObjectId.class); } @Override public void serialize(ObjectId value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { jgen.writeString(value.toString()); } } 

And this is what should change in your @Configuration -menual class:

 @Bean(name = "jsonView") public MappingJacksonJsonView jsonView() { final MappingJacksonJsonView mappingJacksonJsonView = new MappingJacksonJsonView(); mappingJacksonJsonView.setContentType("application/json"); mappingJacksonJsonView.setObjectMapper(new CustomObjectMapper()); return mappingJacksonJsonView; } 

Basically you tell Jackson how to serialize / deserialize this particular object. It works like a charm.

+1
source

I just needed to get getId () to return a String. This was the only way to get Jackson to stop serializing ObjectId.

 public String getId() { if (id != null) { return id.toString(); } else { return null; } } public void setId(ObjectId id) { this.id = id; } 

setId () should still be ObjectId, so Mongo (and its driver) can correctly set the identifier.

+1
source

Source: https://habr.com/ru/post/1393764/


All Articles