基于json格式的玩家数据兼容
Contents
前言
游戏开发中,玩家数据格式不是一成不变的,保证玩家数据格式变更后玩家上线后依然能够进行游戏是基本原则。 本文主要阐述数据库是Mysql时,以玩家表human为例子说明玩家数据兼容的一些方法。
CREATE TABLE `human` (
`uid` int(10) NOT NULL COMMENT '玩家唯一ID',
`name` varchar(50) COLLATE utf8_unicode_ci DEFAULT '' COMMENT '玩家名字',
`head` varchar(50) COLLATE utf8_unicode_ci DEFAULT '[1,1,3]' COMMENT '当前头像',
`exp` int(10) unsigned DEFAULT '0' COMMENT '当前经验',
`level` int(3) unsigned DEFAULT '0' COMMENT '当前等级',
`age` int(3) unsigned DEFAULT '0' COMMENT '玩家年龄',
`gold` bigint(20) unsigned DEFAULT '0' COMMENT '当前元宝数',
`diamond` bigint(20) unsigned DEFAULT '0' COMMENT '当前钻石数量',
`VIP` int(2) unsigned DEFAULT '0' COMMENT 'VIP等级',
`ctGetSkin` text COLLATE utf8_unicode_ci COMMENT '已获得不重复皮肤CfgId',
PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='玩家基础信息';
human对象结构
{
uid:0,
name:'',
exp:0,
level:0,
age:0,
gold:0,
diamond:0,
VIP:0,
ctGetSkin:'{}'
}
一、增删某个字段
eg.策划需求变更,需要删除human.age字段 1.直接删除tb human.age字段 2.删除human实例化对象中age属性
二、字段数据类型变更
eg.uid从int类型转换为varchar 1.tb human.age字段类型能强转,直接转换 1.1 human实例化对象中uid属性调整为string
2.human中uid类型不能强转,uid字段可以变更 2.1 采用增删字段的解决方式
3.human中uid类型不能强转,uid字段不可以变更 3.1 新建字段内uid_1 3.2 写策略把uid值调整为目标格式,写到uid_1内 3.3 删除uid字段,uid_1字段重命名为uid
3.*的方式不推荐,操作复杂,容易出错。
三、字段内数据内容格式变更
eg. ctGetSkin:‘{id:{num},id:{num}}’ => ctGetSkin:‘{id:{num, liftTime},id:{num, liftTime}}’ 1.tb human.ctGetSkin 字段不变更 1.1 skin对象的添加lifeTime属性 1.2 调整ctGetSkin的解析方式,ctGetSkin = OnLoadCtGetSkin(reqly.ctGetSkin);
//CtGetSkin对象
function CtGetSkinDefault() {
return {};
}
//Skin对象
function SkinDefault() {
return {
num:1,
lifeTime:-1,
}
}
//对象兼容解析
function ObjCompatible(tarObj, srcObj) {
if(!srcObj) {
return tarObj;
}
if(typeof srcObj === 'string'){
srcObj = JSON.parse(srcObj);
}
if(typeof srcObj !== 'object'){
return tarObj;
}
for(let i in tarObj){
let k = i + '';
if(srcObj[k] === undefined || srcObj[k] === null) {
continue;
}
if(typeof tarObj[k] === 'object') {
ObjCompatible(tarObj[k], srcObj[k]);
continue;
}
tarObj[k] = srcObj[k];
}
return tarObj;
}
//数据解析容错
function OnLoadCtGetSkin(data) {
let ret = CtGetSkinDefault();
if(typeof data === 'string') {
data = JSON.parse(data);
}
if(typeof data !== 'object') {
return ret;
}
//应该做一个属性递归判断
for(let k in ret) {
if(data[k] === undefined || data[k] === null) {
continue;
}
ret[k] = ObjCompatible(SkinDefault(), data[k]);
}
}
归纳总结
分析完上面三个场景解决方案,发现OnLoadCtGetSkin的这种方式可以通用。只要设计好一套的human解析方式,兼容问题代码方面基本不会出问题,所有关注点就在table调整上了。
Author wangkm
LastMod 2018/07/02