无损 json

无损 json

解析 JSON,不会有丢失数字信息的风险。

'lossless-json' 导入 { parse, stringify }

const text = '{"十进制":2.370,"长":9123372036854000123,"大":2.3e+500}'

// JSON.parse 将丢失一些数字和一个整数:
console.log(JSON.stringify(JSON.parse(text)))
// '{"小数":2.37,"长":9123372036854000000,"大":空}'
// 哎呀!!!

// LosslessJSON.parse 将保留所有数字,甚至格式:
console.log(stringify(解析(文本)))
// '{"小数":2.370,"长":9123372036854000123,"大":2.3e+500}'

以下深入文章解释了那里发生的情况:[为什么 JSON.parse 会损坏大量数字以及如何解决此问题?](https://jsoneditoronline.org/indepth/parse/why-does-json-parse-corrupt- 大数/)

它是如何工作的? 该库的工作方式与本机“JSON.parse”和“JSON.stringify”完全相同。 不同之处在于“lossless-json”保留了大数字的信息。 lossless-json 不会将数值解析为常规数字,而是解析为 LosslessNumber,这是一个将数值存储为字符串的轻量级类。 人们可以使用“LosslessNumber”执行常规操作,当这会导致信息丢失时,它会抛出错误。

何时使用? 如果您必须处理包含“长”值的 JSON 数据,例如来自 C++、Java 或 C# 等应用程序的 JSON 数据。 代价是“lossless-json”比原生的“JSON.parse”和“JSON.stringify”函数慢,因此当性能成为您的瓶颈时要小心。

特征:

  • 处理大数字时没有丢失数字信息的风险。
  • 保持数字的格式。
  • 重复键上的解析错误。
  • 对“bigint”的内置支持。
  • 对“日期”的内置支持(默认关闭)。
  • 可定制:将数值解析为任何数据类型,例如“BigNumber”、“bigint”、“number”或它们的混合。
  • 与本机内置的“JSON.parse”和“JSON.stringify”兼容。
  • 解析无效 JSON 时提供有用的错误消息。
  • 适用于浏览器和 Node.js。
  • 附带 TypeScript 打字功能。
  • 模块化:ES模块功能,仅加载和捆绑您使用的内容。
  • 压缩和压缩后,完整包的大小小于 4kB。

## 安装

通过 npm 安装:

npm 安装lossless-json

## 使用

解析和字符串化

解析和字符串化按照您习惯的方式工作:

'lossless-json' 导入 { parse, stringify }

const json = parse('{"foo":"bar"}') // {foo: 'bar'}
const text = stringify(json) // '{"foo":"bar"}'

无损数字

数字被解析为“LosslessNumber”,可以像数字运算中的常规数字一样使用。 如果转换为数字会因截断、上溢或下溢而导致信息丢失,则会引发错误。

'lossless-json' 导入 { parse }

const text = '{"正常":2.3,"长":123456789012345678901,"大":2.3e+500}'
const json = 解析(文本)

console.log(json.normal.isLosslessNumber) // true
console.log(json.normal.valueOf()) // 数字, 2.3

// LosslessNumbers 可以用作常规数字
console.log(json.normal + 2) // 数字, 4.3

// 但是下面的操作会抛出错误,因为它会导致信息丢失
console.log(json.long + 1)
// 抛出错误:无法安全地将 LosslessNumber 转换为数字:
// "123456789012345678901" 将被解析为 123456789012345680000 并丢失信息

大整数

JavaScript 原生支持“bigint”:可以容纳大量数字的大整数,而不是常规“number”可以容纳的大约 15 位数字。 一个典型的用例是将整数解析为“bigint”,并将所有其他值解析为常规“number”。 这可以通过自定义“numberParser”来实现:

'lossless-json' 导入 { parse, isInteger }

// 将整数值解析为 bigint,否则使用常规数字
导出函数customNumberParser(值){
   返回 isInteger() ? BigInt() : parseFloat()
}

常量文本 = '[123456789123456789123456789, 2.3, 123]'
const json = 解析(文本,null,customNumberParser)
// 输出:
// [
// 123456789123456789123456789n, // bigint
// 2.3, // 数字
// 123n // bigint
//]

您可以使用“isInteger”、“isNumber”、“isSafeNumber”等实用函数根据自己的喜好调整逻辑。 上面显示的数字解析器包含在库中,名为“parseNumberAndBigInt”。

验证安全号码

如果您想将 json 字符串解析为具有常规数字的对象,但想验证没有丢失数字信息,您可以编写自己的数字解析器并使用“isSafeNumber”来验证数字:

'lossless-json' 导入 { parse, isSafeNumber }

函数 parseAndValidateNumber() {
   if (!isSafeNumber()) {
     抛出新错误(`无法安全地将值'$ {value}'转换为数字`}

   返回parseFloat()
}

// 如果全部都解析成功值可以用数字表示
让 json = parse('[1,2,3]', 未定义, parseAndValidateNumber)
console.log(json) // [1, 2, 3](常规数字)

// 当某些值太大而无法正确表示为数字时会抛出错误
尝试 {
   让 json = parse('[1,2e+500,3]', 未定义, parseAndValidateNumber)
} 捕获(错误){
   console.log(err) // 抛出错误 '无法安全地将值 '2e+500' 转换为数字'
}

大数字

将该库与您最喜欢的 BigNumber 库结合使用,例如 decimal.js。 您必须定义自定义数字解析器和字符串生成器:

'lossless-json' 导入 { parse, stringify }
从“decimal.js”导入 Decimal

const parseDecimal = () => new Decimal()

常量十进制字符串符 = {
   测试:(值)=> Decimal.isDecimal(值),
   stringify: () => value.toString()
}

// 解析 JSON,对 Decimal 值进行操作,然后再次字符串化
const 文本 = '{"值":2.3e500}'
const json = parse(text, undefined, parseDecimal) // {value: new Decimal('2.3e500')}
常量输出 = {
   // {结果: new Decimal('4.6e500')}
   结果:json.value.times(2)
}
const str = stringify(输出, 未定义, 未定义, [decimalStringifier])
// '{"结果":4.6e500}'

复兴者和替代者

该库与本机“JSON.parse”和“JSON.stringify”兼容,并且还附带可选的“reviver”和“replacer”参数,允许您以自定义方式序列化例如数据类。 下面的示例演示了如何以与内置“reviveDate”实用程序函数不同的方式对“Date”进行字符串化。

以下示例将“Date”字符串化为带有“$date”键而不是字符串的对象,因此在解析结构时它是唯一可识别的:

'lossless-json' 导入 { parse, stringify }

// 将日期字符串化为具有键“$date”的唯一对象,因此它是可识别的
函数customDateReplacer(键,值){
   if (值实例日期) {
     返回 {
       $date: value.toISOString()
     }
   }

   返回值
}

函数 isJSONDateObject() {
   返回值 && typeof value === 'object' && typeof value.$date === 'string'
}

函数customDateReviver(键,值){
   if (isJSONDateObject()) {
     返回新日期(值。$日期)
   }

   返回值
}

常量记录 = {
   消息:“你好世界”,
   时间戳:新日期('2022-08-30T09:00:00Z'}

const text = stringify(记录,customDateReplacer)
控制台.log(文本)
// 输出:
// '{"message":"Hello World","timestamp":{"$date":"2022-08-30T09:00:00.000Z"}}'

const 已解析 = 解析(文本,customDateReviver)
console.log(已解析)
// 输出:
// {
// 动作: '创建',
// 时间戳: new Date('2022-08-30T09:00:00.000Z')
// }

API

parse(text [, reviver [, parseNumber]])

LosslessJSON.parse() 函数将字符串解析为 JSON,可以选择转换解析产生的值。

  • @param {string} 文本
    要解析为 JSON 的字符串。 有关 JSON 语法的说明,请参阅 JSON 对象。
  • @param {(键:字符串,值:JSONValue)=> 未知} [reviver]
    如果是函数,则规定在返回之前如何转换最初由解析生成的值。
  • @param {函数(值:字符串):未知} [parseNumber]
    传递可选的自定义数字解析器。 输入是一个字符串,输出可以是任何数值:“number”、“bigint”、“LosslessNumber”或自定义“BigNumber”库。 默认情况下,所有数值都被解析为“LosslessNumber”。
  • @returns {未知}
    返回与给定 JSON 文本对应的对象。
  • @throws 如果要解析的字符串不是有效的 JSON,则抛出 SyntaxError 异常。

stringify(值 [, 替换符 [, 空格 [, numberStringifiers]]])

LosslessJSON.stringify() 函数将 JavaScript 值转换为 JSON 字符串,如果指定了替换函数,则可选择替换值;如果指定了替换数组,则可选择仅包含指定的属性。

  • @param {未知}值
    要转换为 JSON 字符串的值。
  • @param {((键:字符串,值:未知) => 未知) | 数组。<字符串| 数字>} [替换]
    更改字符串化过程行为的函数,或包含字符串或数字的数组,用作白名单,用于选择要包含在 JSON 字符串中的值对象的属性。 如果此值为“null”或未提供,则对象的所有属性都将包含在生成的 JSON 字符串中。
  • @param {数字 | 字符串| 未定义} [空格]
    用于在输出 JSON 字符串中插入空格以提高可读性的“字符串”或“数字”。 如果这是一个“数字”,则表示用作空白的空格字符数。 小于 1 的值表示不应使用空间。 如果这是一个“字符串”,则“字符串”将用作空格。 如果未提供此参数(或者为“null”),则不使用空格。
  • @param {数组<{测试:(值:未知)=> 布尔值,字符串化:(值:未知)=> 字符串}>} [numberStringifiers]
    带有附加数字字符串生成器的可选列表,例如用于序列化“BigNumber”。 函数的输出必须是有效的字符串化 JSON 数字。 当返回“undefined”时,该属性将从对象中删除。 与使用“replacer”的区别在于,“replacer”的输出必须是 JSON,并且随后将被字符串化,而“numberStringifiers”的输出已经是字符串化的 JSON。
  • @returns {string | 未定义}
    返回 JSON 对象的字符串表示形式。
  • @throws 当“numberStringifiers”之一未返回有效输出时抛出语法错误。

无损号码

#### 建造

new LosslessNumber(值: 数字 | 字符串) : LosslessNumber

#### 方法

  • .valueOf(): 数字 | 大整数
    将“LosslessNumber”转换为常规“number”或“bigint”。 对于仅丢失一些无意义数字的安全数字和十进制值,将返回“数字”。 对于大整数,返回“bigint”。 对于将溢出或下溢的值,将引发“错误”。 例子:

    // 安全号码
    console.log(new LosslessNumber('23.4').valueOf())
    // 数字 23.4
    
    // 丢失小数位的小数
    console.log(new LosslessNumber('0.666666666666666666666667').valueOf())
    // 数字 0.6666666666666666
    
    // 一个大整数
    console.log(new LosslessNumber('9123372036854000123').valueOf())
    // bigint 9123372036854000123
    
    // 一个会溢出的值
    console.log(new LosslessNumber('2.3e+500').valueOf())
    // 错误:无法安全地转换为数字:值“2.3e+500”会溢出并变为无穷大
    
    // 一个会下溢的值
    console.log(new LosslessNumber('2.3e-500').valueOf())
    // 错误:无法安全地转换为数字:值“2.3e-500”将下溢并变为 0
    

    请注意,您可以实现自己的转换策略,只需通过“.toString()”获取字符串形式的值,然后使用“isInteger”、“isSafeNumber”、“getUnsafeNumberReason”和“toSafeNumberOrThrow”等实用函数将其转换为 一个数值。

  • .toString() : 字符串
    获取无损数的字符串表示形式。

#### 特性

  • {boolean} .isLosslessNumber : true
    无损数字包含一个属性“isLosslessNumber”,可用于
    检查某个变量是否包含 LosslessNumber。

实用函数

  • isInteger(值: 字符串) : 布尔值
    测试字符串是否包含整数值,例如“2300”或“10”。

  • isNumber(值:字符串):布尔值
    测试字符串是否包含数值,例如“2.4”或“1.4e+3”。

  • isSafeNumber(value: string, config?: { approx: boolean }): boolean
    测试字符串是否包含可以用 JavaScript“数字”安全表示的数值,而不会丢失任何信息。 当数字被截断为整数或小数时,或者当数字上溢或下溢时,返回 false。 当传递 { approx: true } 作为配置时,该函数将不那么严格,并且允许丢失小数值的无意义数字。 例子:

    isSafeNumber('1.55e3') // true
    isSafeNumber('2e500') // false
    isSafeNumber('2e-500') // false
    isSafeNumber('9123372036854000123') // false
    isSafeNumber('0.66666666666666666667') // false
    isSafeNumber('9123372036854000123', { approx: true }) // false
    isSafeNumber('0.66666666666666666667', { approx: true }) // true
    
  • toSafeNumberOrThrow(value: string, config?: { approx: boolean }) : number
    在安全的情况下将字符串转换为数字,否则抛出信息性错误。

  • getUnsafeNumberReason(value): UnsafeNumberReason | 未定义
    当提供的“value”是不安全数字时,请描述原因:“overflow”、“underflow”、“truncate_integer”、“truncate_float”。 当值安全时返回“未定义”。

  • isLosslessNumber(值:未知):布尔值
    测试一个值是否是“LosslessNumber”。

-toLosslessNumber(值:数字):LosslessNumber
将“数字”转换为“无损数字”。 当“number”超过 15 位数字的最大安全限制(因此被截断)或者为“NaN”或“Infinity”时,该函数将引发异常。

  • parseLosslessNumber(value: string) : LosslessNumber
    “parse”使用的默认“numberParser”。 从包含数值的字符串创建“LosslessNumber”。

-parseNumberAndBigInt(值:字符串):数字| 大整数
可由“parse”使用的自定义“numberParser”。 解析器会将整数值转换为“bigint”,并将所有其他值转换为常规“number”。

  • reviveDate(键,值)
    将包含 ISO 8601 日期字符串的字符串恢复为 JavaScript“Date”对象。 默认情况下,此恢复程序未打开,因为将_意外_包含日期的文本字段解析为“日期”的风险很小。 reviveDate 是否可以安全使用取决于用例。 用法:

    'lossless-json' 导入 { parse, reviveDate }
    
    const data = parse('["2022-08-25T09:39:19.288Z"]', reviveDate)
    // 输出:
    // [
    // 新日期('2022-08-25T09:39:19.288Z')
    //]
    

    另一种解决方案是在特定的可识别对象中字符串化“Date”,例如“{‘$date’:‘2022-08-25T09:39:19.288Z’}”,并使用恢复器和替换器将此对象转换为 “日期”,反之亦然。

## 备择方案

类似的库:

  • https://github.com/sidorares/json-bigint
  • https://github.com/nicolasparada/js-json-bigint
  • https://github.com/epoberezkin/json-source-map

## 测试

要测试该库,首先安装依赖项一次:

npm 安装

要运行单元测试:

npm测试

要构建库并运行单元测试和集成测试:

npm 运行构建和测试

棉绒

运行 linting:

npm 运行 lint

自动修复 linting 问题:

npm 运行格式

## 基准

要运行基准测试来比较与本机“JSON”解析器的性能:

npm 运行基准测试

(剧透:“lossless-json”比原生慢得多)

## 建造

要构建捆绑和缩小的库 (ES5),请首先安装依赖项一次:

npm 安装

然后捆绑代码:

npm 运行构建

这将在文件夹“./.lib”中生成 ES 模块输出和 UMD 包,可以在浏览器和 Node.js 中执行并在浏览器中使用。

### 发布

发布新版本:

$ npm 运行发布

这会:

  • 棉绒
  • 测试
  • 建造
  • 增加版本号
  • 将更改推送到 git,添加 git 版本标签
  • 发布npm包

要尝试构建并查看更改列表而不实际发布:

$ npm run 发布-试运行

## 执照

根据 MIT 许可证 发布。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无损检测手册pdf是一种电子文档格式的无损检测参考指南。无损检测是一种通过非破坏性方法来评估材料和构件的完整性和质量的技术。这种手册提供了无损检测的详细信息,包括原理、设备和工艺以及各种无损检测方法的应用。它是无损检测人员和相关专业人士的重要工具,能够提供准确和有效的检测指导。 无损检测手册pdf具有以下几个优点。首先,它是以电子文档的形式提供,可以在电脑、平板电脑或手机上随时随地进行查阅。这样方便了人们对无损检测的学习和实践。其次,该手册提供了丰富的内容,涵盖了各个无损检测方法的原理、仪器设备的使用和维护,以及实际案例和应用指南。这使得读者可以全面了解无损检测的各个方面,提高自己的技能和知识。最后,该手册具有良好的可搜索性和交互性,读者可以根据自己的需求快速找到所需信息,并与其他读者进行交流和互动。 尽管无损检测手册pdf具有许多优点,但也存在一些局限性。首先,作为电子文档,读者需要有合适的设备和软件来阅读和使用这种类型的手册。另外,由于无损检测技术和设备的不断发展,该手册可能不具备最新的信息。因此,读者需要注意参考手册的版本和发布日期,确保获取到的信息是最新的。 总的来说,无损检测手册pdf是一种方便、全面和实用的工具,对于无损检测人员和相关专业人士来说是非常有价值的资料。它提供了丰富的无损检测知识和技术,帮助人们提高工作效率和准确性。然而,读者在使用该手册时也需要关注信息的时效性并灵活运用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值