资讯专栏INFORMATION COLUMN

由JSON序列化失败引起的对序列化过程配置的思考

kyanag / 2480人阅读

摘要:报错信息部分代码片段对象实例导致序列化错误当然解决方式有很多种,在最初版本的代码开发过程中,由于部分业务的缺失,暂时把空位补上,而其表示的其实就是空对象,导致序列化时报错。解决方法第一种方法直接把替换为,即可解决序列化错误问题。

问题描述

本次遇到问题时所使用的框架是Spring Boot,处理完请求之后,返回数据之前,在POJO转化成JSON时,有些属性违背输出规则或者有些属性循环引用会造成无法输出。

报错信息:org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class java.lang.Object and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.lang.Object and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

部分代码片段:

    @Override
    public ReviewReportDto getReviewReport(String requestId) {
        ReviewReportDto resDto = new ReviewReportDto();
        ...
        ...
        //Object对象实例导致序列化错误
        resDto.setOffLineDto(new Object());
        return resDto;
    }

当然解决方式有很多种,在最初版本的代码开发过程中,由于部分业务的缺失,暂时把空位补上new Object(),而其表示的其实就是null(空对象),导致序列化时报错。

解决方法

第一种方法:
直接把new Object()替换为null,即可解决序列化错误问题。

第二种方法
通过设置,使Jackson遇到空对象不抛异常。

    @Bean("objectMapper")
    public ObjectMapper myMapper() {
        return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    }

第三种方法(spring mvc项目)
通过xml配置自定义类来覆盖默认配置

    //自定义类
    public class MyMapper extends ObjectMapper {
        public MyMapper() {
            configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
        }
    }
    
    
        
            ...
            
                ...
                
                
                    
                    
                
            
        
    
序列化过程配置的规整

此处贴出SerializationFeature的源码,以及对部分常用配置方式的总结:

package com.fasterxml.jackson.databind;

import com.fasterxml.jackson.databind.cfg.ConfigFeature;

public enum SerializationFeature implements ConfigFeature {

    //是否环绕根元素,默认false,如果为true,则默认以类名作为根元素。根元素名称也可以通过@JsonRootName来自定义。
    WRAP_ROOT_VALUE(false),

    //是否缩放排列输出,默认false,有些场合为了便于排版阅读则需要对输出做缩放排列
    INDENT_OUTPUT(false),

    //遇到空对象则失败
    FAIL_ON_EMPTY_BEANS(true),

    //自我引用则失败
    FAIL_ON_SELF_REFERENCES(true),

    //com.fasterxml.jackson.annotation.JsonUnwrapped包下相关联的类将会抛出异常
    WRAP_EXCEPTIONS(true),


    FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS(true),
    CLOSE_CLOSEABLE(false),
    FLUSH_AFTER_WRITE_VALUE(true),
    WRITE_DATES_AS_TIMESTAMPS(true),

    //序列化日期时以timestamps输出,默认true
    WRITE_DATE_KEYS_AS_TIMESTAMPS(false),

    WRITE_DATES_WITH_ZONE_ID(false),
    WRITE_DURATIONS_AS_TIMESTAMPS(true),

    //序列化char[]时以json数组输出,默认false
    WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS(false),

    //序列化枚举是以toString()来输出,默认false,即默认以name()来输出
    WRITE_ENUMS_USING_TO_STRING(false),

    //序列化枚举是以ordinal()来输出,默认false
    WRITE_ENUMS_USING_INDEX(false),

    WRITE_NULL_MAP_VALUES(true),
    /** @deprecated */
    @Deprecated
    WRITE_EMPTY_JSON_ARRAYS(true),

    //序列化单元素数组时不以数组来输出,默认false
    WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED(false),

    /** @deprecated */
    @Deprecated
    //序列化BigDecimal时之间输出原始数字还是科学计数,默认false,即是否以toPlainString()科学计数方式来输出
    WRITE_BIGDECIMAL_AS_PLAIN(false),
    WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(true),

    //序列化Map时对key进行排序操作,默认false
    ORDER_MAP_ENTRIES_BY_KEYS(false),

    EAGER_SERIALIZER_FETCH(true),
    USE_EQUALITY_FOR_OBJECT_ID(false);

    private final boolean _defaultState;
    private final int _mask;

    private SerializationFeature(boolean defaultState) {
        this._defaultState = defaultState;
        this._mask = 1 << this.ordinal();
    }

    public boolean enabledByDefault() {
        return this._defaultState;
    }

    public int getMask() {
        return this._mask;
    }

    public boolean enabledIn(int flags) {
        return (flags & this._mask) != 0;
    }
}

By the way:引用请标明出处。如有错误,请批评指正。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67862.html

相关文章

  • Hadoop学习热身——HDFS概念

    摘要:助辅助做元数据的备份。元数据存储在内存和磁盘中,这是因为磁盘的读写效率较低,而保存到内存又有断电消失的隐患。但磁盘中的元数据并不是最新的,内存中的元数据才是实时的。将中的和复制到自身节点上并加载进内存,根据的记录操作更改元数据信息。 HDFS(Hadoop Distributed File System ) 前言:最近正式进入了大数据框架的学习阶段,文章来自个人OneNote笔记全部...

    AnthonyHan 评论0 收藏0
  • springboot学习(三)——使用HttpMessageConverter进行http列化和反

    摘要:序列化反序列化主要体现在程序这个过程中,包括网络和磁盘。如果是开发应用,一般这两个注解对应的就是序列化和反序列化的操作。协议的处理过程,字节流内部对象,就涉及这两种序列化。进行第二步操作,也就是序列化和反序列化的核心是。 以下内容,如有问题,烦请指出,谢谢! 对象的序列化/反序列化大家应该都比较熟悉:序列化就是将object转化为可以传输的二进制,反序列化就是将二进制转化为程序内部的...

    stackfing 评论0 收藏0
  • Elasticsearch学习上手(二)

    摘要:序列化被大多数编程语言所支持,并且已经成为领域的标准格式。通过索引对文档的进行创建查询修改和删除等操作。请求的结构调整为不再使用请求使用这个存储这个文档,而是使用请求存储文档在这个命名空间下。 在安装elasticsearch之后,我们就要开始进行操作实践,那么在实践之前,我们首先了解下elasticsearch的几个概念 面向文档 相对关系型数据库,是采用行和列的形式进行存储数据,e...

    stdying 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<