跳至主要內容

字段序列化

Mr.Hope大约 3 分钟

字段序列化

序列化属性:

  • serialize: 后端序列化函数 SerializeEnum 或者 自定义序列化函数,默认为serialize.NON(NON或缺省就是JSON)
    • 可选值:
    • JSON:JSON格式
    • XML:XML格式(暂不支持)
    • COMMA:逗号分隔格式
    • DOT:点分隔格式
  • requestSerialize: 前端序列化函数 SerializeEnum 或者 自定义序列化函数,默认为serialize.NON(NON或缺省就是JSON)

数据存储的序列化

使用@Field注解的serialize属性来配置非基础类型属性的序列化与反序列化方式,最终会以序列化后的字符串持久化到存储中。

实现数据存储序列化的举例:

在PetItem中配置两个字段petItemDetails类型为List<PetItemDetail>和tags类型为List<String>,并设置为不同的序列化方式,petItemDetails为JSON(缺省就是JSON,可不配),tags为COMMA。同时设置 @Field.Advanced(columnDefinition = "varchar(1024)")防止序列化后存储过长

@Model.model(PetItemDetail.MODEL_MODEL)
@Model(displayName = "商品详情",summary = "商品详情",labelFields = {"remark"})
public class PetItemDetail extends TransientModel {
    public static final String MODEL_MODEL="demo.PetItemDetail";

    @Field.String(min = "2",max = "20")
    @Field(displayName = "备注",required = true)
    private String remark;

    @Field(displayName = "备注人",required = true)
    private PamirsUser user;

}
@Model.model(PetItem.MODEL_MODEL)
@Model(displayName = "宠物商品",summary="宠物商品",labelFields = {"itemName"})
public class PetItem  extends CodeModel{

    public static final String MODEL_MODEL="demo.PetItem";

    @Field(displayName = "详情", serialize = Field.serialize.JSON, store = NullableBoolEnum.TRUE)
    @Field.Advanced(columnDefinition = "varchar(1024)")
    private List<PetItemDetail> petItemDetails;

    @Field(displayName = "商品标签",serialize = Field.serialize.COMMA,store = NullableBoolEnum.TRUE,multi = true)
    @Field.Advanced(columnDefinition = "varchar(1024)")
    private List<String> tags;

}

添加字段数据,查看商品数据表,我们可以看到【详情】字段和【商品标签】字段,按指定序列化方式进行存储

字段序列化注意点

  1. 必须使用Field#store属性将字段存储设置为NullableBoolEnum.TRUE
  2. 使用Field#serialize属性指定序列化方式,默认为JSON。
  3. 如把PetItemDetail设置为存储模型,须在PetItem的petItemDetails字段上使用Field.Relation#store属性将关联关系存储设置为false。不然会同时存储petItemDetails字段和对应的PetItemDetail表记录

字段序列化方式说明

序列化方式说明备注
JSONJSON序列化主要用于模型相关类型字段的序列化,是@Field.serialize默认选项
DOT点拼接集合元素
COMMA逗号拼接集合元素
BIT按位与,2次幂数求和非@Field.serialize可选项列表,用于二进制枚举序列化不需要配置,由oinone自动推断

注册自己的序列化器

注册自己的序列化器(实现pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer接口), 如oinone的DOT的序列化方式,用type()方法返回值做匹配,serialize和deserialize分别对应序列化和反序列化方法。

package pro.shushi.pamirs.framework.compute.serialize;

import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer;
import pro.shushi.pamirs.meta.common.constants.CharacterConstants;
import pro.shushi.pamirs.meta.enmu.SerializeEnum;
import pro.shushi.pamirs.meta.util.TypeUtils;

/**
 * 点表达式序列生成处理器实现
 *
 * @author d@shushi.pro
 * @version 1.0.0
 * date 2020/3/4 2:48 上午
 */
@SuppressWarnings("rawtypes")
@Slf4j
@Component
public class DotSerializeProcessor implements Serializer<Object, String> {

    @Override
    public String serialize(String ltype, Object value) {
        if (null == value) {
            return null;
        }
        if (List.class.isAssignableFrom(value.getClass())) {
            return StringUtils.join((List) value, CharacterConstants.SEPARATOR_DOT);
        } else {
            return StringUtils.join(Collections.singletonList(value), CharacterConstants.SEPARATOR_DOT);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object deserialize(String ltype, String ltypeT, String value, String format) {
        if (null == value) {
            return null;
        }
        String[] dots = value.split(CharacterConstants.SEPARATOR_ESCAPE_DOT);
        List list = new ArrayList();
        for (String dot : dots) {
            Object object = TypeUtils.valueOfPrimary(ltypeT, dot, null);
            list.add(object);
        }
        return list;
    }

    @Override
    public String type() {
        return SerializeEnum.DOT.value();
    }
}

字段默认值的反序列化

@Field.defaultValue注解在字段上配置defaultValue属性时,将根据字段的Ttype类型及字段的Ltype等类型属性,自动进行反序列化。包括但不限于以下几种情况:

  • OBJ、STRING、TEXT、HTML——保持不变
  • BINARY、INTEGER——转换为整数
  • FLOAT、MONEY——转换为浮点数
  • DATETIME、DATE、TIME、YEAR——根据Field.Date#format属性决定反序列化日期格式
  • BOOLEAN——仅允许null、true、false
  • ENUM——使用value进行匹配