小程序json数据精度丢失问题

探讨了在使用JS处理后台返回的Long类型数据时,因超过Number类型精度限制导致的问题,并提供两种解决方案:一是后台将Long转为String返回;二是前端通过自定义解析策略,将Number类型转换为String,确保精度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天在做小程序,发现后台返回Long类型时,js按照Number类型进行处理,那么这就会产生数据如果大于9007199254740992就会出现精度丢失,因为Long的范围是-9223372036854775808~9223372036854775808 (-2^63~2^63),而js中Number的范围为-9007199254740992~9007199254740992(-2^53 ~2^53),

有两种解决方案

1.后台Long转为String返回

但是由于小程序接口是用手机app的,如果改的话可能会导致app有问题,还有一个就是接口太多,几乎所有的id都用的Long类型返回,所以采用第二种方法

2.如果是Number就转换为String,再进行Json.parse()

因为小程序默认数据返回类型是json,所以要将默认类型设置为text,而后遍历每个节点的数据类型,如果是Number,大于2^53次方就直接转换为String

  /**
   * 请求
   */
  _request(action, method, data, suc, fail, dataType) {

    wx.request({
      url: wx.getStorageSync('url') + action + "?method=" + method,
      data: arguments[2] == undefined||arguments[2] == ""?"":data,
      header: header,
      method: "Post",
      dataType:'text',
      success: (res) => {
        res.data = this.getRealJsonData(res.data)
 
      },
      fail: (e)=>{
        
          wx.showToast({
            icon: "none",
            title: "请求失败,请检查网络"
          });
          return
      },
      complete:()=>{
        setTimeout(function () {
     wx.hideLoading()
    }, 500)
      }
    })
  }
  /**
   * 因为js中的Json.parse()会让Number数据类型精度丢失,因此这个自己写一下
   */
  getRealJsonData(baseStr) {
  if (!baseStr || typeof baseStr != 'string') return;
  var jsonData = null;
  try {
    jsonData = JSON.parse(baseStr);
  } catch (err) {
    return null;
  }
  var needReplaceStrs = [];
  this.loopFindArrOrObj(jsonData, needReplaceStrs);
  needReplaceStrs.forEach(function (replaceInfo) {
    var matchArr = baseStr.match(eval('/"' + replaceInfo.key + '":[0-9]{15,}/'));
    if (matchArr) {
      var str = matchArr[0];
      var replaceStr = str.replace('"' + replaceInfo.key + '":', '"' + replaceInfo.key + '":"');
      replaceStr += '"';
      baseStr = baseStr.replace(str, replaceStr);
    }
  });
  var returnJson = null;
  try {
    returnJson = JSON.parse(baseStr);
  } catch (err) {
    return null;
  }
  return returnJson;
}

/**
 * 遍历对象类型的
 */
getNeedRpStrByObj(obj, needReplaceStrs) {
  for (var key in obj) {
    var value = obj[key];
    // 大于这个数说明精度会丢失!
    if (typeof value == 'number' && value > 9007199254740992) {
      needReplaceStrs.push({ key: key });
    }
    this.loopFindArrOrObj(value, needReplaceStrs);
  }
}

/**
 * 判断数据类型
 */
getNeedRpStrByArr(arr, needReplaceStrs) {
  for (var i = 0; i < arr.length; i++) {
    var value = arr[i];
    this.loopFindArrOrObj(value, needReplaceStrs);
  }
}
/**
 * 递归遍历
 */
loopFindArrOrObj(value, needRpStrArr) {
  var valueTypeof = Object.prototype.toString.call(value);
  if (valueTypeof == '[object Object]') {
    needRpStrArr.concat(this.getNeedRpStrByObj(value, needRpStrArr));
  }
  if (valueTypeof == '[object Array]') {
    needRpStrArr.concat(this.getNeedRpStrByArr(value, needRpStrArr));
  }
}

 

                 

<think>嗯,用户想了解记账微信小程序数据库设计遇到的问题。首先,我需要回忆一下数据库设计的一般步骤和常见问题。记账小程序的核心功能包括记录收支、分类管理、用户账户、报表统计等,所以数据库设计需要围绕这些功能展开。 首先,用户需求分析是关键。可能遇到的问题包括需求不明确,比如用户是否需要多账户支持,或者分类是否允许自定义。如果需求分析没做好,后续设计可能会有偏差,导致频繁修改表结构,影响开发进度。 接下来是数据表结构设计。主表比如账单表,需要考虑字段是否全面,比如金额、类型、时间、分类、备注等。外键关联用户表和分类表。这里可能出现的问题包括字段类型不合适,比如金额用浮点数导致精度丢失,应该用DECIMAL类型。还有索引的设计,如果没有为常用查询字段加索引,比如按月份查询,可能会影响性能。 然后是关联关系设计。比如用户和账单是一对多,分类和账单也是一对多。如果分类表设计成树形结构支持多级分类,可能需要父级ID字段,但处理起来复杂。外键约束是否启用也需要考虑,启用外键可以保证数据一致性,但可能影响性能,特别是在频繁插入删除时。 数据一致性和完整性方面,比如删除用户时,如何处理其账单记录。是否需要级联删除,或者设置为null,这会影响业务逻辑。还有分类被删除后,账单中的分类ID可能变成无效,需要处理这些脏数据。 性能优化方面,随着数据量增加,查询账单列表可能会变慢。需要考虑分页查询,或者按时间分区。账单统计报表涉及大量计算,是否需要定时任务预聚合数据,比如每日统计结果存入汇总表,避免实时计算压力。 安全性问题,用户数据隐私很重要,比如账单信息需要加密存储,数据库访问权限控制,防止SQL注入攻击。备份和恢复机制也需要设计,避免数据丢失。 扩展性和灵活性,比如后期想加新功能,比如预算管理、多币种支持,数据库是否需要预留字段或者设计得更灵活。但过度设计也会导致表结构复杂,维护困难。比如使用EAV模式存储动态字段,虽然灵活但查询效率低。 实际开发中的挑战,比如微信小程序云开发使用的是NoSQL数据库,如云开发数据库,与传统关系型数据库设计不同,可能需要调整设计思路。比如云数据库不支持JOIN操作,需要冗余存储或多次查询,这会影响设计方式。 还有测试阶段的数据模拟问题,需要生成大量测试数据来验证性能,比如百万条账单记录,测试查询和统计速度,及时发现瓶颈。 可能用户没有考虑到的问题,比如多端同步,如果在手机和网页端都有入口,如何保证数据一致性,解决冲突。或者离线情况下记录账单,之后同步到服务器时的冲突处理。 总结一下,常见的问题包括需求分析不充分、表结构设计不合理、索引缺失、关联关系处理不当、数据一致性维护困难、性能瓶颈、安全漏洞、扩展性不足,以及云开发环境下的特殊限制等。解决这些问题需要综合考虑业务需求、技术选型和未来扩展,反复验证和优化设计。</think>记账微信小程序数据库设计可能遇到以下关键问题及解决方案,采用结构化方式呈现: 1. **需求分析不明确** - 典型问题:忽略多账户/家庭成员共享场景 - 解决方式:添加 `account_type` 字段(个人/共享),设计 `family_members` 关联表 2. **核心表结构设计** ```sql /* 账单表(核心表)*/ CREATE TABLE bills ( bill_id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, -- 关联用户表 amount DECIMAL(12,2) NOT NULL, -- 金额使用精确小数 type ENUM('income','expense') DEFAULT 'expense', category_id INT NOT NULL, -- 关联分类表 record_time DATETIME NOT NULL, remark VARCHAR(255), INDEX idx_time(user_id, record_time) -- 复合索引 ); ``` 3. **高频问题:分类管理** - 痛点:用户需要自定义分类但影响数据统计 - 解决方案: ```sql /* 支持系统预置+用户自定义的分类表 */ CREATE TABLE categories ( category_id INT PRIMARY KEY, name VARCHAR(20) NOT NULL, is_custom TINYINT DEFAULT 0, -- 0-系统/1-用户自定义 parent_id INT DEFAULT 0 -- 支持二级分类 ); ``` 4. **性能优化难点** - 问题:统计年度报表时查询缓慢 - 优化方案: ```sql /* 添加汇总表预存每日统计 */ CREATE TABLE daily_summary ( user_id INT NOT NULL, summary_date DATE NOT NULL, total_income DECIMAL(12,2) DEFAULT 0, total_expense DECIMAL(12,2) DEFAULT 0, PRIMARY KEY(user_id, summary_date) ); ``` 5. **数据一致性挑战** - 场景:删除分类时处理关联账单 - 采用逻辑删除方案: ```sql ALTER TABLE categories ADD is_deleted TINYINT DEFAULT 0; -- 0-有效 1-删除 /* 查询时自动过滤已删除分类 */ SELECT * FROM bills WHERE category_id IN ( SELECT category_id FROM categories WHERE is_deleted=0 ); ``` 6. **安全设计要点** - 敏感字段加密存储示例: ```sql /* 银行账户信息表 */ CREATE TABLE bank_accounts ( account_id INT PRIMARY KEY, user_id INT NOT NULL, account_name VARBINARY(255), -- 加密存储 account_number VARBINARY(255) ); ``` 7. **云开发特殊限制** - 微信云数据库解决方案: ```javascript // 云函数处理关联查询 exports.getBillDetail = async (event) => { const { billId } = event; const bill = await db.collection('bills').doc(billId).get(); const category = await db.collection('categories').doc(bill.categoryId).get(); return { ...bill.data, categoryName: category.data.name }; }; ``` **典型问题处理流程**: 1. 用户反馈"分类显示异常" 2. 排查步骤: - 检查 `categories` 表的 `is_deleted` 状态 - 验证账单查询中的分类过滤逻辑 - 审计分类删除操作的日志记录 3. 常见根因:误删系统预置分类 4. 修复方案:恢复系统分类并设置 `is_system=1` 保护 **扩展设计建议**: - 添加 `budgets` 预算表支持限额提醒 - 使用 `JSON` 字段存储扩展属性(如票据照片链接) - 增加 `data_version` 字段实现多端同步 建议在正式开发前使用工具生成测试数据验证设计,例如: ```python # 生成10万条测试账单数据 import random from datetime import datetime, timedelta def generate_test_data(user_count=1000, days=365): start_date = datetime.now() - timedelta(days=days) for _ in range(100000): yield { 'user_id': random.randint(1, user_count), 'amount': round(random.uniform(1, 5000), 2), 'type': random.choice(['income', 'expense']), 'category_id': random.randint(1, 50), 'record_time': start_date + timedelta( seconds=random.randint(0, days*86400)) } ``` 通过系统日志监控高频查询,持续优化索引策略。建议每周执行一次 `EXPLAIN` 分析慢查询。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值