Java Jackson框架使用小技巧

介绍

Jackson框架:
  Jackson是一个简单的、功能强大的、基于Java的应用库。它可以很方便完成Java对象和Json对象(xml文档or其它格式)进行互转。Jackson社区相对比较活跃,更新速度也比较快。
  Jackson库有如下几大特性:
   - 高性能且稳定:低内存占用,对大/小JSON串,大/小对象的解析表现均很优秀
   - 流行度高:是很多流行框架的默认选择 - 容易使用:提供高层次的API,极大简化了日常使用案例
   - 无需自己手动创建映射:内置了绝大部分序列化时和Java类型的映射关系
   - 干净的JSON:创建的JSON具有干净、紧凑、体积小等特点
   - 无三方依赖:仅依赖于JDK - Spring生态加持:jackson是Spring家族的默认JSON/XML解析器

maven引入依赖:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.13.5</version>
</dependency>

目录(持续更新)

1.场景一,对于属性,我们在基于父子类或者自身情况,限制属性的权限,顺带了解下JsonProperty注解的使用
2.场景二,如何将对象转为json字符串、json字符串转对象。
3.配置一个类在转json时忽略值为null的属性(或只包含不为null的属性)

1.场景一,对于属性,我们在基于父子类或者自身情况,限制属性的权限,顺带了解下JsonProperty注解的使用:

// 与数据库对应的类
public class SysPermission implements Serializable {
    private Integer id;
    private String flag;
}
// 用于用户提交的接收对象,但是我不希望用户传入id被我接收到,可以以下的方式设置
public class SysPermissionReq extends SysPermission {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Override
    public Integer getId() {
        return super.getId();
    }
}

在上面我们用到了@JsonProperty注解:

public @interface JsonProperty {
    // 指示处理程序应使用属性的默认名称(派生自方法或字段名称)的特殊值。
    String USE_DEFAULT_NAME = "";
    // 用于指示未指定索引的标记值。用作默认值作为注释不允许“缺失”值。
    int INDEX_UNKNOWN = -1;
    // 定义逻辑属性的名称,即用于属性的 JSON 对象字段名称。如果值为空字符串(这是默认值),将尝试使用带注释的字段的名称。请注意,构造函数参数 没有可用的默认名称,这意味着 空字符串不是构造函数参数的有效值。
    String value() default "";
    // 用于支持此类概念的数据格式(特别是 XML)的可选命名空间;如果是这样,则使用 用于 value 构造完全限定名称。
    String namespace() default "";
    // 指示在反序列化期间属性是否需要值(可能是显式 null)的属性。如果预期,应将此指示为有效性问题(通常通过抛出异常,但这可以通过问题处理程序发送,这些问题处理程序可以尝试纠正问题,例如, BeanDeserialized 通过提供默认值)。
    // 请注意,从 2.6 开始,此属性仅用于创建者属性,以确保 JSON 中存在属性值:对于其他属性(使用资源库或可变字段注入的属性),不执行验证。将来可能会添加对这些情况的支持。此属性的状态通过内省公开,其值通常由架构生成器使用,例如 JSON 架构生成器。
    boolean required() default false;
    // 指示此属性的数字索引(相对于为对象指定的其他属性)的属性。此索引通常由二进制格式使用,但也可能对架构语言和其他工具有用。
    int index() default -1;
    // 可用于 记录 属性的预期默认值的属性:最常用作生成架构(如 JSON 架构或 protobuf/thrift 架构)或文档的源信息。它也可以由杰克逊扩展模块使用;核心“Jackson-Databind”除了简单地通过 Bean 属性自检公开此值之外,没有任何自动处理。
    // 将来此注释可能会用于值默认值,尤其是 Creator 属性的默认值,因为它们在 2.6 及更高版本中支持 required() 。
    String defaultValue() default "";
    // 可选属性,可用于更改确定访问器(getter、字段作为 getter)和突变器(构造函数参数、setter、字段作为 setter)的可见性的方式,以便可以使用其他不可见的访问器(如私有 getter);或者忽略其他可见的访问器。
    // 默认值 os JsonProperty.Access.AUTO ,这意味着访问权限仅根据可见性和其他注释确定。
    Access access() default JsonProperty.Access.AUTO;
    // 属性的各种 access 选项,指定在序列化(“读取”)和反序列化(“写入”)期间如何访问属性(请注意,读取和写入的方向是从属性的角度,而不是从外部数据格式:这在某些情况下可能会令人困惑)。
    // 请注意,虽然此批注修改了对带批注属性的访问,但其效果可能会被属性进一步覆盖 JsonIgnore :如果两个批注都存在于访问器上, JsonIgnore 则优先于此属性。但是,此注释属性优先于使用“拆分” JsonIgnore/JsonProperty 组合
    public static enum Access {
        // 访问设置,这意味着可见性规则将用于自动确定此属性的读取和/或写入访问权限。
        AUTO,
        READ_ONLY,
        WRITE_ONLY,
        READ_WRITE;
        private Access() {
        }
    }

2.场景二,如何将对象转为json字符串、json字符串转对象。

/**
 * @author LiusCraft
 * @DateTime 2023/5/8 22:36
 */
public class JsonUtils {
    private static final ObjectMapper mapper = new ObjectMapper();
    public static ObjectMapper getMapper() {
        return mapper;
    }
    public static String JsonToString(Object object) {
        try {
            return getMapper().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "{}";
        }
    }
    public static <T> T JsonToObject(String json, Class<T> tClass) {
        try {
            return mapper.readValue(json, tClass);
        } catch (JsonProcessingException e) {
            return null;
        }
    }
}

3.配置一个类在转json时忽略值为null的属性

@JsonInclude(JsonInclude.Include.NON_NULL)

以下例子中,在类上加上上面的注解即可是实现Json中不包含NULL值的属性存在到JSON数据中

@ApiModel(
        value = "JSON统一响应数据体",
        description = "在进行ajax请求时,返回的JSON格式,通过ok来决定数据是否正常"
)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AjaxResult <T> implements Serializable {
    static final long serialVersionUID = 1L;
    @ApiModelProperty("状态码")
    private int code;
    @ApiModelProperty("是否成功")
    private boolean ok;
    @ApiModelProperty("消息")
    private String msg;
    @ApiModelProperty("数据")
    private T data;
    @ApiModelProperty("map数据, 附加属性列,实际请求为准")
    private HashMap<String, Object> map;
}

例如我请求了我的测试项目中的获取权限列表接口(该接口不存在附加数据(map数据)):
我们可以看到响应体中就不会出现key为map的内容。
image

posted @ 2023-05-17 12:07  LiusCraft  阅读(177)  评论(0编辑  收藏  举报