springboot mybatisplus enum 枚举返回中文描述, 动态转换成相应的描述
springboot mybatisplus enum 枚举返回描述
背景: 我根据例子写了个 枚举类 ArticleStateEnum 然后在实体类 Article 中的 articleState 字段得类型改成 ArticleStateEnum 然后运行查询的时候, 返回的是枚举类的 "变量名字"
例如: NotReviewed(0, "未审核") 这里 NotReviewed 就是变量名,
其实这里返回的是枚举类一条数据的一个对象比如"NotReviewed(0, "未审核")"返回的是这一条数据的对象,然后你可以 用这个对象 调用 如下枚举类中的"getCode()" 和 "getDesc()" 等方法, 但是这对象转成json输出后 就 只剩了 变量名 NotReviewed 了, 我想要 json输出 "未审核"
但是我 想要 在查询中返回的是 描述 即 "NotReviewed(0, "未审核")" 中的"未审核"这几个字
解决: 在枚举类里 加一个 public String toString() 方法 具体如下 枚举类 中 然后在实体类相应的 字段 上方添加注解 @JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString) 如下实体类中 然后重启运行 , 状态输出中文了
枚举类:
package com.wenhe.blogdao.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import java.util.Objects;
@Getter
public enum ArticleStateEnum {
NotReviewed(0, "未审核"),
Reviewed(1, "审核通过"),
Reject(2, "驳回");
@EnumValue
private final Integer code;
public int getCode() {
return this.code;
}
@JsonValue
private final String desc;
public String getDesc(){
return desc;
}
ArticleStateEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static String getDesc(int code) {
for (ArticleStateEnum value : ArticleStateEnum.values()) {
if (Objects.equals(code, value.getCode())) {
return value.getDesc();
}
}
return null;
}
@Override
public String toString() {
return this.desc;
}
}
实体类:
package com.wenhe.blogdao.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.wenhe.blogdao.model.enums.ArticleStateEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.experimental.Accessors;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("bk_article")
public class Article extends Model<Article> {
private static final long serialVersionUID = 1L;
@TableId(value = "article_id", type = IdType.AUTO)
private Integer articleId;
/**
* 0 未审核 不显示 ,, 1 会员发布未审核,,2 审核通过 ,, 3 草稿箱 ,, 4回收站 ,,
*/
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
@TableField("article_state")
private ArticleStateEnum articleState;
@Override
protected Serializable pkVal() {
return this.articleId;
}
}
application.yml mybatisplus 配置
mybatis-plus:
mapper-locations: classpath*:com/wenhe/blogdao/mapper/mapping/**.xml
type-aliases-package: com.wenhe.blogdao.model
global-config:
db-config:
id-type: AUTO #0:数据库ID自增 1:用户输入id 2:全局唯一id(IdWorker) 3:全局唯一ID(uuid)
logic-delete-value: 0
logic-not-delete-value: 1
configuration:
map-underscore-to-camel-case: false
cache-enabled: true #配置的缓存的全局开关
lazyLoadingEnabled: true #延时加载的开关
multipleResultSetsEnabled: true #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
type-enums-package: com.wenhe.blogdao.model.enums
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用
参考资料
(。・v・。)fastjson+mybatis-plus中枚举类的使用
在使用mybaits-plus中(官网链接:链接)的时候,有个枚举类的功能的十分常见,因为在实际开发中,少不了约定一些状态码以及特殊含义的数字等,这就与枚举类中的意义相同,fastjson+mybatis-plus可以让实际开发中
- 动态转换成相应的描述,无需进行显式、重复的状态转换
- 约定需修改时,也方便统一修改
一、 定义枚举类
- 要点
- 建议实现
IEnum<T>
接口@EnumValue
标记在数据库存的字段上,下述例子数据存的就是 code字段,即 0,1- 重写
toString
方法,返回相应的描述,这个在序列化时会替换成这个描述package com.example.demo.user.enumClass; import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.core.enums.IEnum; /** * Create by Lingo */ //@JSONType(serializeEnumAsJavaBean = true) public enum GenderEnum implements IEnum<Integer> { MALE(1,"男"), FEMALE(0,"女"); @EnumValue private final int code; private final String descp; GenderEnum(int code, String descp) { this.code = code; this.descp = descp; } @Override public String toString() { return this.descp; } @Override public Integer getValue() { return code; } }
- 要点
- 实现
Serializable
接口,以便可以序列化- 需要转换的字段的类型应该是 枚举类,而不是数据库的类型,如本例的 gender 数据库的类型是
tinyint(1)
,而定义的时候类型是GenderEnum
- 需要转换的字段应加入
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
注解,以便进行局部设置package com.example.demo.user.entity; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.serializer.SerializerFeature; import com.example.demo.user.enumClass.GenderEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; /** * @author Lingo * @since 2019-08-06 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @ApiModel(value="User对象", description="") public class User implements Serializable { private static final long serialVersionUID = 1L; private String name; private Integer age; private String email; @JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString) private GenderEnum gender; // setter/getter方法已经由lombok 在编译时自动生成 }
实体类\Controller\Service都可以使用
Mybatis-plus
的CodeGenerator
来自动生成,此处不再演示,具体请看Mybatis-plus
的官网三、配置
Mybatis-plus
# application.yml # 指定扫描枚举类所在包 mybatis-plus: type-enums-package: com.example.demo.user.enumClass
- 要点
- 要使用
Json.toJsonString
的方法才能获取描述(调用枚举类的toString
方法)。当使用Json.toJson()
的时候,则不会替换成描述。原因请看后面package com.example.demo; import com.alibaba.fastjson.JSON; import com.example.demo.user.entity.User; import com.example.demo.user.service.IUserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class DemoApplicationTests { @Autowired IUserService userService; @Test public void selectList1(){ System.out.println("----------test1--------------"); List<User> userList = userService.lambdaQuery().list(); for (User user : userList) { System.out.println(JSON.toJSONString(user)); } } @Test public void selectList2(){ System.out.println("----------test2--------------"); List<User> userList = userService.lambdaQuery().list(); for (User user : userList) { System.out.println(JSON.toJSON(user)); } } @Test public void selectList3() { System.out.println("----------test3--------------"); List<User> userList = userService.lambdaQuery().list(); for (User user : userList) { System.out.println(user); } } @Test public void selectList4() { System.out.println("----------test4--------------"); List<User> userList = userService.lambdaQuery().list(); userList.forEach(System.out::println); } }
----------test1-------------- {"age":24,"email":"test1@baomidou.com","gender":"女","name":"Jone"} {"age":24,"email":"test2@baomidou.com","gender":"女","name":"Jack"} {"age":24,"email":"test3@baomidou.com","gender":"男","name":"Tom"} {"age":24,"email":"test4@baomidou.com","gender":"男","name":"Sandy"} {"age":24,"email":"test5@baomidou.com","gender":"女","name":"Billie"} ----------test2-------------- {"gender":"FEMALE","name":"Jone","age":24,"email":"test1@baomidou.com"} {"gender":"FEMALE","name":"Jack","age":24,"email":"test2@baomidou.com"} {"gender":"MALE","name":"Tom","age":24,"email":"test3@baomidou.com"} {"gender":"MALE","name":"Sandy","age":24,"email":"test4@baomidou.com"} {"gender":"FEMALE","name":"Billie","age":24,"email":"test5@baomidou.com"} ----------test3-------------- User(name=Jone, age=24, email=test1@baomidou.com, gender=女) User(name=Jack, age=24, email=test2@baomidou.com, gender=女) User(name=Tom, age=24, email=test3@baomidou.com, gender=男) User(name=Sandy, age=24, email=test4@baomidou.com, gender=男) User(name=Billie, age=24, email=test5@baomidou.com, gender=女) ----------test4-------------- User(name=Jone, age=24, email=test1@baomidou.com, gender=女) User(name=Jack, age=24, email=test2@baomidou.com, gender=女) User(name=Tom, age=24, email=test3@baomidou.com, gender=男) User(name=Sandy, age=24, email=test4@baomidou.com, gender=男) User(name=Billie, age=24, email=test5@baomidou.com, gender=女)
package com.example.demo.user.controller; import com.alibaba.fastjson.JSON; import com.example.demo.user.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Lingo * @since 2019-08-06 */ @RestController @RequestMapping("/user") public class UserController { @Autowired IUserService userService; @RequestMapping("/list") public Object list(){ // 至于为什么要先变成JSONString 再组装成 JSON,请看后文 return JSON.toJSON(JSON.toJSONString(userService.lambdaQuery().list())); } }
为什么要先用
toJsonString
再组装成Json
对象
JSON.toJSONString()
在研究
toJsonString()
方法的时候,发现fastjson
自己也有一个ObjectSerializer
的对象池,当你在实体类中标记了@JSONField
注解的时候,它就会根据 实体类的类型返回相对应的ObjectSerializer
(序列化器),先看以下代码:public final void write(Object object) { if (object == null) { this.out.writeNull(); } else { Class<?> clazz = object.getClass(); ObjectSerializer writer = this.getObjectWriter(clazz); // 1 号代码 try { writer.write(this, object, (Object)null, (Type)null, 0); // 2号代码 } catch (IOException var5) { throw new JSONException(var5.getMessage(), var5); } } }
- 当实体类中有
@JSONField
注解时,1 号代码中将会返回JavaBeanSerializer
,此时2号代码将会调用javaBeanSerializer
的write 方法,期间,FieldSerializer
会判断这个Field
是不是Enum
,如果是,则取toString
的值。关键代码如下:if (this.fieldInfo.isEnum) { //here if (this.writeEnumUsingName) { serializer.out.writeString(((Enum)propertyValue).name()); return; } if (this.writeEnumUsingToString) { serializer.out.writeString(((Enum)propertyValue).toString()); return; } }
- 当实体类中有
@JSONField
注解时,1 号代码中将会返回ASMSerializer_x_xxx
如(ASMSerializer_1_User
),估计是在项目初始化的期间通过反射产生的,断点调试时此时2号代码会调用Serializable.writeDirect()
方法,由于在代码上这个方法是返回 boolean类型的,且名称也不对,并没有对输出做什么操作,猜测是使用了Aop技术(具体是什么没有做深入研究)。这里会直接将所有的Field
值转成json格式,而fastjson是默认使用Name
属性的,如本例的(MALE/FEMALE
)
JSON.toJSON()
if (clazz.isEnum()) { return ((Enum)javaObject).name(); }