如何使用Jackson将嵌套的ObjectId序列化为String?

时间:2016-04-08 08:27:53

标签: java json spring jackson

关于杰克逊从ObjectIdString的转换有many questions。所有答案都建议您创建自己的JsonSerializer<ObjectId>或使用ObjectId注释@JsonSerialize(using = ToStringSerializer.class)字段。

但是,我有一张有时包含ObjectIds的地图,即:

class Whatever {
  private Map<String, Object> parameters = new HashMap<>();
  Whatever() {
    parameters.put("tom", "Cat");
    parameters.put("jerry", new ObjectId());
  }
}

我希望杰克逊将其转换为:

{
  "parameters": {
    "tom": "cat",
    "jerry": "57076a6ed1c5d61930a238c5"
  }
}

但我明白了:

{
  "parameters": {
    "tom": "cat",
    "jerry": {
      "date": 1460103790000,
      "machineIdentifier": 13747670,
      "processIdentifier": 6448,
      "counter": 10631365,
      "time": 1460103790000,
      "timestamp": 1460103790,
      "timeSecond": 1460103790
    }
  }
}

我已经使用

注册了转换(在Spring中)
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);
  }
}

第一级ObjectIds已正确转换。如何让杰克逊转换成嵌套的?我是否必须为此地图编写自定义转换器?

请记住,此Map可以多次嵌套(即包含其他地图)。我只想在杰克逊看到它时将ObjectId转换为String

2 个答案:

答案 0 :(得分:3)

我认为你从org.bson.types.ObjectId开始约org.springframework.boot:spring-boot-starter-data-mongodb。你的代码对我来说非常好。我可以看到的一件事是你没有在@Configuration之上显示WebappConfig注释。

这是我的演示项目,你可以在你的设置上进行测试吗?

<强> 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;
        }
    }
}

回复127.0.0.1:8080

{
  "parameters": {
    "tom": "Cat",
    "jerry": "5709df1cf0d9550b4de619d2"
  }
}

<强>摇篮:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-mongodb")
    compile("org.springframework.boot:spring-boot-starter-web")
}

答案 1 :(得分:0)

感谢 varren 的回答,它在 springMvc 的旧版本中运行良好。 但从 5.0 开始,WebMvcConfigurerAdapter 已被弃用。 解决方案:

  1. 可能不工作解决方案:我们可以直接为 mvc 配置实现 WebMvcConfigurer。但有些配置可能不起作用,因为 WebMvcConfigurationSupport 的优先级更高。
  2. 建议解决方案:我们可以直接扩展 WebMvcConfigurationSupport。暗示configureMessageConverters方法可以添加我们需要的各种自定义HttpMessageConverters,它可以在默认转换器之前正常工作。

spring 框架是一个了不起的框架,等我有时间再深入研究一下。(●'◡'●)