当前位置: 首页 > 知识库问答 >
问题:

如何手动使用springs默认对象映射器/手动反序列化HTTP请求主体到对象

朱博实
2023-03-14

我有一个通用的Rest-Constroller,它需要从一个实体名中构造一个实体,一个表示实体属性的请求体。我需要手动将请求体映射到目标类。

我已经尝试了不同的方法来自定义RestController反序列化数据的方式,并且认为我当前的方法是最简单的。我现在注册一个@PostMapping,并检索用于确定正确类的entityName和一个@RequestBody字符串entityJson,我通过ObjectMapper将其转换为确定的类。

然而,我在LocalDate反序列化过程中遇到了一些问题(注意:我的日期字符串的格式为'yyyy-mm-dd't'hh:mm:ss.sssz',其中时间为零)。

我使用带有jpa 2.1.9的springboot 2.1.6.Release,因此,如果我使用@RequestBody XXXEntity实体参数,则不需要自定义处理RestControllers中的LocalDate/LocalDateTime属性。但是,当向我的RestController注入OnjectMapper bean并尝试ObjectMapper.readValue(entityJson,entityClass)时,反序列化在LocalDate属性上失败。

1.)没有自定义配置异常:com.fasterxml.jackson.databind.exc.invaliddefinitionException:无法构造java.time.localdate的实例(没有创建器,如默认构造,存在):没有字符串参数构造函数/工厂方法可以从字符串值反序列化('2019-10-29t00:00:00.000z')

2.)使用自定义JSR310Module ObjecktMapper时

dateTimeParseException:无法分析文本“2019-10-29t00:00:00.000z”,在索引10中找到未分析的文本

        ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
                .serializationInclusion(JsonInclude.Include.NON_NULL)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 
                .modules(new JSR310Module())
                .build();
Same error with custom DateFormat:
  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        objectMapper.setDateFormat(df);
 Jackson2ObjectMapperBuilder.json()
    .deserializerByType(LocalDate.class, LocalDateTimeDeserializer.INSTANCE)

结果变得更好...因此,当我击中UTC timezon:java.time.format.dateTimeParseException时,解析失败:无法解析文本'2019-10-29t00:00:00.000z',未解析文本位于索引23

这就是我的控制器的样子:

    @Autowired
    public AdminRestController(EntityService entityService, ObjectMapper objectMapper) {
        this.entityService = entityService;
        this.objectMapper = objectMapper;
    }

...

    @Transactional
    @PostMapping(value = "/entities/{entityName}")
    public List<T> createEntity(@PathVariable String entityName, @RequestBody String entityJson) {
        T newEntity = constructEntity(entityName, entityJson);
        entityService.create(newEntity);
        ...
    }
...
    private T constructEntity(String entityName, String entityJson) {
        Class<T> entityClass;
        try {
            entityClass = findClassByName(entityName);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("Entity " + entityName + " unknwon.");
        }
        try {
            T entity = objectMapper.readValue(entityJson, entityClass);
            return entity;
        } catch (IOException e) {
            throw new IllegalStateException("Unable to construct entity  " + entityName + " from provided data.", e);
        }
    }

共有1个答案

杭涵映
2023-03-14

你可能会认为这很古怪。我对逻辑的看法是:

    if (string.isEmpty()) {
        return null;
    }
    if (string.endsWith("Z")) {
        return Instant.parse(string).atZone(ZONE_SWISS).toLocalDate();
    }
    return LocalDate.parse(string, DateTimeFormatter.ISO_LOCAL_DATE_TIME);

我避免了对字符串的修改和从LocalDateTimeLocalDate的转换。另外,由于z只能排在字符串的最后,所以我的版本提供了preciser验证。最后,我喜欢string.isempty方法。

 类似资料:
  • 我使用此链接中的以下代码为我的一个数据模型类(JSON到JAXB模型的转换)添加自定义反序列化程序。 我想使用com。fasterxml。杰克逊。jaxrs。json。JacksonJaxbJsonProvider,用于其他数据模型的JSON序列化/反序列化。 JacksonJaxbJsonProvider的默认实现非常适合我的JAXB模型,将超类作为抽象类。但是,一旦我提供了自己的自定义Obje

  • 这适用于顶级对象,但不适用于嵌套对象。例如,如果嵌套对象是特殊对象,则仍将其反序列化为公共对象。 我想做的是告诉Jackson:“无论嵌套级别如何,如果ObjType=Special,使用SpecialObject,否则使用GeneralObject”。我研究了多态反序列化,并尝试使用@JSONSubtypes,但无法正确设置该逻辑。如何确保特殊对象被反序列化到适当的类中,即使它们是嵌套的?

  • 你好,我有下一个json响应: 正如你所见,我有一个资源对象,里面有许多不同的对象,但这些对象可能会根据输入的不同而有所不同。我创建了下一个pojo: 在我的输入Pojo中: 导入java。util。列表 我将资源添加为对象列表,但我可以看到它是一个对象,其中包含不同的对象。如何将这些不同的对象映射到Java中的对象?事实上,我需要计算我有多少资源,但我正在努力实现这一目标。谢谢!

  • 我有一个有内部地图的POJO。我想将它从JSON反序列化为HashMap,但Jackson将JSON的内部映射反序列化为LinkedHashMap。我可以通过将映射的类型从“Map”更改为“HashMap”来强制它使用HashMap,但我想知道是否有方法告诉Jackson将反序列化为Map的特定实现? 这里是JSON: 和转换类: 如何使用ObjectMapper:

  • 我有一个已经序列化的JSON字符串。从源序列化时,未忽略null属性值。因此,对象的序列化输出类似于: 现在,如果我在Java中使用对象映射器反序列化上面的内容,它会抛出一个异常,指向value not Available。对象映射器是否可以将“姓氏”反序列化回“null”?我可以配置对象映射器在这种情况下不会失败吗?