import { test } from 'node:test' import assert from 'node:assert/strict' import { parseJsonObject, sanitizeWellFormedUnicode, deepSanitizeUnicode, safeJsonStringify, wrapLargeIntegerLiterals, } from './json.js' import type { JsonObject } from '../types/json.js' test('sanitizeWellFormedUnicode handles null bytes and lone surrogates', () => { // Null byte assert.equal(sanitizeWellFormedUnicode('hello\0world'), 'helloworld') // Lone high surrogate \ud835 const loneSurrogate = 'nickname\ud835test' const cleaned = sanitizeWellFormedUnicode(loneSurrogate) assert.equal(cleaned, 'nickname\uFFFDtest') // Valid emoji surrogate pair \uD83D\uDE00 (😀) should remain intact const validEmoji = 'Hello 😀' assert.equal(sanitizeWellFormedUnicode(validEmoji), 'Hello 😀') }) test('deepSanitizeUnicode recursively cleans objects and arrays', () => { const input = { user: 'buyer\ud83c', nested: { comment: 'good\0deal', tags: ['cool\ud835', 'ok'], }, } const output = deepSanitizeUnicode(input) assert.deepEqual(output, { user: 'buyer\uFFFD', nested: { comment: 'gooddeal', tags: ['cool\uFFFD', 'ok'], }, }) }) test('safeJsonStringify produces valid JSON safe for postgres jsonb', () => { const input = { orderSn: '260919-123456', nickname: '\ud835\ud83c*buyer', nullByte: 'abc\0def', } const json = safeJsonStringify(input) assert.ok(typeof json === 'string') const parsed = JSON.parse(json) assert.equal(parsed.nickname, '\uFFFD\uFFFD*buyer') assert.equal(parsed.nullByte, 'abcdef') }) test('preserveLargeIntegers:19 位 id 不被压精度(真实踩坑)', () => { // 真实案例:抖店 product_id 真值 …567,直接 JSON.parse 会变成 …600 const raw = '{"code":"10000","data":{"sku_order_list":[{"code":"幸运币2个","product_id":3847255376114352567,"sku_id":3383719439799589,"pay_amount":100}]}}' assert.equal(JSON.parse(raw).data.sku_order_list[0].product_id, 3847255376114352600) const safe = parseJsonObject(raw, { preserveLargeIntegers: true }) const row = (safe.data as JsonObject).sku_order_list as JsonObject[] assert.equal(row[0]?.product_id, '3847255376114352567') // 16 位但未超 MAX_SAFE_INTEGER 的数字保持不变(不误伤) assert.equal(row[0]?.sku_id, 3383719439799589) // 小整数保持数字类型 assert.equal(row[0]?.pay_amount, 100) }) test('preserveLargeIntegers:不动字符串里的数字,也不动短数字', () => { const raw = '{"order_id":"6930318258716179555","note":"单号6930318258716179555","pay_time":1791521705}' const safe = parseJsonObject(raw, { preserveLargeIntegers: true }) assert.equal(safe.order_id, '6930318258716179555') assert.equal(safe.note, '单号6930318258716179555') assert.equal(safe.pay_time, 1791521705) }) test('wrapLargeIntegerLiterals 只包裹超大整数字面量', () => { assert.equal(wrapLargeIntegerLiterals('{"a":123}'), '{"a":123}') assert.equal(wrapLargeIntegerLiterals('{"a":3847255376114352567}'), '{"a":"3847255376114352567"}') assert.equal( wrapLargeIntegerLiterals('{"a":"3847255376114352567"}'), '{"a":"3847255376114352567"}', ) })