放弃fastjson拥抱jackson

放弃fastjson 拥抱jackson

背景

  • 功能强大 好用;不亏是国人更懂国人;但是安全漏洞频发;生产项目总是告警 勒令修改 放弃使用。
  • 坑爹玩意fastjson 漏洞太多 直接搞了fastjson2;虽然大部分兼容 远古项目还需要升级谁敢动呀。动了引发一些未知BUG那岂不是背锅侠(玩笑 该干还得干 挣得就是这个钱)

安全漏洞

  • 产生原因:序列化和反序列化;无非就是反序列化的时候能够注入调用一些非法函数。攻击者可以构造特殊的序列化数据包,当目标系统尝试反序列化这些数据时,恶意代码就会被执行

替代方案

  • 都是JSON 序列化框架 跟着spring大腿学习使用springboot 默认序列化框架jackson
  • jackson 运行是占用内存较低 性能较好

jackjson 模块

  • jackson-databind数据绑定
  • jackson-core用于JSON解析和生成
  • jackson-annotations 用于注解支持

1. 核心类

  • ObjectMapper

2.JackJson 序列化API

普通对象

复杂对象

List

Map

以上序列化使用writeValueAsString方法均可以 暂无特别之处

日期处理

  • 默认Date类型序列化成时间戳
  • 代用ObjectMapper setDateFormat 方法设置日期序列化转换格式 (SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");)

4.Jackjson 反序列化API

  1. jackson通过将JSON字段的名称与Java对象中的getter和setter方法进行匹配,将JSON对象的字段映射到Java对象中的属性。
  2. Jackson删除了getter和setter方法名称的“ get”和“ set”部分,并将其余名称的第一个字符转换为小写。

4.1 普通字符串反序列化(都有现成api暂不提供示例)

Jackjson 支持输入json字符串反序列化

Jackjson 支持输入文件反序列化

Jackjson 支持输入字节流反序列化

Jackjson 支持输入url反序列化

Jackjson 支持输入字节数组反序列化

4.2 JSON 数组字符串反序列化(反序列化的时候需要提供TypeReference类型)

JSON 数组字符串 -> Map集合

JSON 数组字符串 -> List集合

JSON 数组字符串 -> 对象数组

5. 支持自定义序列化反序列化示例

5.1 自定义序列化

  SimpleModule version1Module = new SimpleModule();
  //自定义序列化
  version1Module.addSerializer(User.class, new JsonSerializer<User>() {
        @Override
        public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("username", user.getName());
            jsonGenerator.writeNumberField("userage", user.getAge());
            jsonGenerator.writeEndObject();
        }
    });
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(version1Module);

5.2 自定义反序列化

public class UserDeserializer extends StdDeserializer<User> {

    public UserDeserializer() {
        this(null);
    }

    public UserDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public User deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        String name = node.get("name").asText();
        int age = (Integer) ((IntNode) node.get("age")).numberValue();

        return new User(name, age);
    }
}

6. 树模型(JsonNode)

JsonNode 子类实现

  • ObjectNode:对应JSON对象,包含一组键值对,可以通过.put(key, value)添加或更新属性。
  • ArrayNode:对应JSON数组,包含一系列元素,可通过.add(value)插入新元素。
  • TextNode、IntNode、LongNode、DoubleNode等:分别对应JSON中的字符串、整数、长整数、浮点数等基本类型值。
  • BooleanNode、NullNode:分别对应JSON中的布尔值和null值。

7.Jackson注解使用

  1. @JsonIgnore 用于在序列化或反序列化过程中忽略某个属性
  2. @JsonIgnoreProperties (类级别注解) 用于批量指定在序列化或反序列化过程中应忽略的属性列表,特别适用于应对不明确或动态变化的输入 JSON 中可能存在但不应处理的额外字段 ignoreUnknown 为true 会自动忽略Java类型中没有对应的未知属性
  3. @JsonIgnoreType (类级别注解) 忽略某个类都不进行序列化
  4. @JsonProperty 用于指定类的属性在序列化和反序列化成 JSON 时所对应的键名
  5. @JsonFormat 用于指定日期、时间、日期时间以及其他数值类型在序列化和反序列化为 JSON 时的格式
  6. @JsonInclude
    • VALUE_DEFAULT:这是默认策略,意味着所有字段都会被序列化,无论其值是否为 null
    • NON_NULL:只有非 null 的字段会被序列化。这是最常用的策略,可以减少 JSON 输出的大小,尤其是在字段可能经常为 null 的情况下
    • NON_ABSENT:除了 null 值,还会忽略那些未设置(未初始化)的字段。在 Java 中,这意味着除了 null,还会忽略默认值(如 0、false 或空字符串)
    • NON_EMPTY:除了 null 和未初始化的值,还会忽略那些被认为是“空”的值,如空字符串、空集合或空数组
  7. @JsonAnyGetter 用于标记一个方法,获取除已知属性外的所有其他键值对。这些键值对通常存储在一个 Map 结构中,以便将它们作为一个附加的对象进行序列化。
    • 动态属性支持:通过在返回 Map 的方法上使用 @JsonAnyGetter,您可以将一个对象的动态属性集合序列化为 JSON 对象的多个键值对。这些属性可能是在运行时添加的,或者基于某些条件动态生成的。
    • 简化结构:避免为每个可能的动态属性单独声明字段和 getter/setter。只需维护一个 Map,即可处理任意数量和类型的额外属性。
    • 兼容性与灵活性:当需要与未知或未来可能变化的数据结构交互时,@JsonAnyGetter 可确保 JSON 表示能够容纳未预定义的属性,从而提高系统的兼容性和适应性。
  8. @JsonSerialize 指定字段使用特定序列化策略
  9. @JsonDeserialize 指定字段使用特定反序列化策略
  10. @JsonAnySetter 用于处理反序列化过程中遇到的未知或额外的 JSON 键值对。当一个对象的JSON表示中包含无法直接映射到已声明属性的键时,这个注解可以帮助捕获并存储这些额外的数据 反序列化字段是Map类型未明确具体类型
  11. @JsonRawValue 指示Jackson在序列化时应将其原始值视为未经转义的 JSON 字符串,并直接嵌入到输出的 JSON 文档中

8. SpringBoot 如何不覆盖默认的Jackson而是拓展?

  1. 实现WebMvcConfigurer接口并覆盖extendMessageConverters方法
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import java.text.SimpleDateFormat;
    import java.util.List;
    @Configuration
    public class JacksonConfig implements WebMvcConfigurer {
        @Override
        public void extendMessageConverters(List<HttpMessageConverter`<?>> converters) {
            for (HttpMessageConverter<?>` converter : converters) {
                if (converter instanceof MappingJackson2HttpMessageConverter) {
                    ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                    // 在这里配置你的 ObjectMapper
                    // 例如设置日期格式
                    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                }
            }
        }
    }
  1. 使用Customizer接口扩展Jackson行为
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import java.text.SimpleDateFormat;
    import java.util.List;

    @Configuration
    public class JacksonConfig implements WebMvcConfigurer {
        @Override
        public void extendMessageConverters(List<HttpMessageConverter`<?>> converters) {
            for (HttpMessageConverter<?>` converter : converters) {
                if (converter instanceof MappingJackson2HttpMessageConverter) {
                    ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                    // 在这里配置你的 ObjectMapper
                    // 例如设置日期格式
                    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                }
            }
        }
    }
posted @ 2024-08-19 10:41  贺艳峰  阅读(4)  评论(0编辑  收藏  举报