跳至主要內容

json

chanchaw大约 3 分钟languagejava

概述

mysql5.7 开始支持 json 类型的字段,一个字段可保存一个对象,下面介绍从前端到数据库的整个链路上的用法

数据库

下面表结构中的字段 phone_datavisit_datajson 类型的字段

create table visit_submit_log
(
    id bigint auto_increment comment '自增主键'
        primary key,
    parent_id int default 0 null comment '生成访单成功后写入访单主键=visit.id',
    union_id varchar(50) default '' null comment '用户微信unionId',
    entry_time datetime null comment '微信用户进入制作访单页面的时间',
    submit_time datetime null comment '制作访单后提交的时间',
    phone_data json null comment '手机硬件信息',
    visit_data json null comment '访单json数据',
    state int default 1 null comment '状态,默认1有效,0停用',
    is_delete int default 0 null comment '删除标识,默认0未删除,1表示删除。mybatis-flex默认使用该名称作为逻辑删除的标识',
    remark varchar(200) default '' null comment '备注',
    sys_remark varchar(100) default '' null comment '系统备注,系统在做自动化操作时用于说明业务逻辑',
    seq float default 0 null comment '排序序号',
    create_time datetime default CURRENT_TIMESTAMP null comment '创建时间,DB自动填充',
    create_user varchar(100) default '' null comment '创建人',
    update_time datetime null on update CURRENT_TIMESTAMP comment '最后一次修改时间',
    update_user varchar(100) default '' null comment '修改人',
    page_uuid varchar(100) default '' null comment '前端页面唯一标识,每次新打开制作访单页面都会创建一个新的UUID'
)
comment '访单提交记录表,不管是否成功,记录每一次的提交动作';
java

springboot 项目中使用了 mybatis-flex,只需要贴出实体类即可。一开始设置 phoneDatavisitDataMap<String,Object>,前端发送请求后端报错由于没有 gettersetter 无法解析前端数据,后来设置这两个 json 字段数据类型为 String 也测试不同,最后更改为 Object 类型可行。

/**
 * @author chanchaw
 * @create 2025-09-26 12:12
 */
@Table("visit_submit_log")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class VisitSubmitLog implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id(keyType = KeyType.Auto)
    private Long id;
    private Integer parentId;
    private String pageUuid;
    private String unionId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime entryTime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime submitTime;
    @Column(typeHandler = JacksonTypeHandler.class)
    private Object phoneData;
    @Column(typeHandler = JacksonTypeHandler.class)
    private Object visitData;
    private Integer state;
    private Integer isDelete;
    private String remark;
    private String sysRemark;
    private Float seq;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    private LocalDateTime createUser;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    private LocalDateTime updateUser;
}

// 上面是实体类,下面是控制器代码
@PostMapping("/testJsonType")
public ResponseResult testJsonType(@RequestBody VisitSubmitLog record){
    return new ResponseResult(visitSubmitLogMapper.insertSelective(record));
}
微信小程序

微信小程序中声明实体类的代码如下

interface IVisitSubmitLog {
  id?:number,parentId?:number,pageUuid?:string,unionId?:string,entryTime?:Date,submitTime?:Date,phoneData?:string,visitData?:string,state?:number,isDelete?:number,remark?:string,sysRemark?:string,seq?:number,createTime?:Date,createUser?:string,updateTime?:Date,updateUser?:string
}

注意对应 mysql 两个 json 字段的数据类型是 string 类型,请求 API 时传递参数如下:

// 传递进来的参数 formData 是表单对象,visitSubmitLog 是实体类 IVisitSubmitLog 的实例
// 赋值 json 类型属性时不需要 JSON.stringify(),直接赋值对象即可
async insertVisitSubmitLog(formData:IVisit){
    this.setData({
        'visitSubmitLog.visitData': formData
    })
    const affectedRowCount = await http.insertVisitSubmitLogDev$(this.data.visitSubmitLog);
},

// 直接请求后端 API 的函数
// 传入的实体类对象参数 record 也不需要 JSON.stringify()
// 直接赋值给请求的 data 即可
const insertVisitSubmitLogDev$ = (record: IVisitSubmitLog):Promise<number> => {
  console.log('请求参数1:',record);
  return new Promise((resolve,reject) => {
    wx.request({
      header: { "Content-Type": "application/json; charset=UTF-8" }, method: 'POST',
      url: `https://showawx.xdfznh.club/visitorbedev/test/testJsonType`, 
      data: record,
      success: (res: any) => {
        const { success,msg,data } = res.data;
        if(!success) {
          console.log('请求出现异常:', msg);
          wx.showToast({title: msg, icon:'none', duration: 5000});
          reject(data);
          return
        }
        resolve(data);
      },
      fail: (err: any) => {
        console.log('写入 visit_submit_log 时出现异常:',err)
      },
      complete: () => {}
    })
  })
}

小程序用string,Web前端用Object

注意上面的案例在微信小程序中测试通过,其通过下面代码更新对象数据到实体类的 string 属性

this.setData({
    'visitSubmitLog.visitData': formData,
    'visitSubmitLog.submitTime': new Date(),
})

前端的字符串类型属性 visitData 可以直接赋值表单的对象数据,java 后端采用 Object 类型接受数据。如果是 web 前端则属性 visitData 应该设置为 Object 类型