There are many questions concerning conversion from ObjectId
to String
with jackson. All answers suggest either creating own JsonSerializer<ObjectId>
or annotating the ObjectId
field with @JsonSerialize(using = ToStringSerializer.class)
.
However, I have a map that sometimes contains ObjectIds
, i.e.:
class Whatever { private Map<String, Object> parameters = new HashMap<>(); Whatever() { parameters.put("tom", "Cat"); parameters.put("jerry", new ObjectId()); } }
I want jackson to convert it to:
{ "parameters": { "tom": "cat", "jerry": "57076a6ed1c5d61930a238c5" } }
But I get:
{ "parameters": { "tom": "cat", "jerry": { "date": 1460103790000, "machineIdentifier": 13747670, "processIdentifier": 6448, "counter": 10631365, "time": 1460103790000, "timestamp": 1460103790, "timeSecond": 1460103790 } } }
I have registered the conversion (in Spring) with
public class WebappConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder .serializerByType(ObjectId.class, new ToStringSerializer()); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(builder.build()); converters.add(converter); } }
And the first-level ObjectIds
are converted correctly. How to make jackson convert also the nested ones? Do I have to write custom converter for this map?
Keep in mind that this Map
can be nested multiple times (i.e. contain another maps). I just want to convert ObjectId
to String
whenever jackson sees it.
Advertisement
Answer
I suppose that you are taking about org.bson.types.ObjectId
from org.springframework.boot:spring-boot-starter-data-mongodb
. Your code works perfectly fine for me. 1 thing i can see is that you don’t show @Configuration
annotation above WebappConfig
.
Here is my demo project, can you test it on yours setup?
Application.java
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.bson.types.ObjectId; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.util.HashMap; import java.util.List; import java.util.Map; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Configuration public static class WebappConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder .serializerByType(ObjectId.class, new ToStringSerializer()); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(builder.build()); converters.add(converter); } } @RestController public static class MyRestController { @ResponseBody @RequestMapping("/") public Whatever method() { return new Whatever(); } } public static class Whatever { private Map<String, Object> parameters = new HashMap<>(); public Whatever() { parameters.put("tom", "Cat"); parameters.put("jerry", new ObjectId()); } public Map<String, Object> getParameters() { return parameters; } public void setParameters(Map<String, Object> parameters) { this.parameters = parameters; } } }
Responce from 127.0.0.1:8080
{ "parameters": { "tom": "Cat", "jerry": "5709df1cf0d9550b4de619d2" } }
Gradle:
dependencies { compile("org.springframework.boot:spring-boot-starter-data-mongodb") compile("org.springframework.boot:spring-boot-starter-web") }