@compare-json/core(JavaScript)

@compare-json/core 是一个轻量、零依赖的 JavaScript/TypeScript 库,用于深度对比 JSON 值——也是本网站使用的对比引擎。它可以检测两个 JSON 结构之间的新增、删除、类型变更和值变更,并支持细粒度的对比行为控制。

语言:JavaScript/TypeScript —— 通过 npm 分发。其它语言的实现可能会陆续推出。

安装

# npm
npm install @compare-json/core

# yarn
yarn add @compare-json/core

# pnpm
pnpm add @compare-json/core

快速开始

import { compareJSON } from '@compare-json/core';

const baseJSON = { name: 'Alice', age: 30, hobbies: ['reading'] };
const contrastJSON = { name: 'Bob', age: '30', hobbies: ['reading', 'coding'], email: '[email protected]' };

const differences = compareJSON({ baseJSON, contrastJSON });

console.log(differences);
// [
//   { pathSegments: ['name'], pathString: 'name', pathBelongsTo: 'both', diffType: 'valueChanged' },
//   { pathSegments: ['age'], pathString: 'age', pathBelongsTo: 'both', diffType: 'typeChanged' },
//   { pathSegments: ['hobbies', '[1]'], pathString: 'hobbies[1]', pathBelongsTo: 'contrast', diffType: 'added' },
//   { pathSegments: ['email'], pathString: 'email', pathBelongsTo: 'contrast', diffType: 'added' },
// ]

对比选项

import { compareJSON } from '@compare-json/core';

// 将数字字符串视为与数字相等
compareJSON({
  baseJSON: { count: 1 },
  contrastJSON: { count: '1' },
  options: { numericStringEqualsNumber: true },
});
// [](无差异)

// 键名大小写不敏感
compareJSON({
  baseJSON: { Name: 'Alice' },
  contrastJSON: { name: 'Alice' },
  options: { keyCaseInsensitive: true },
});
// [](无差异)

// 值大小写不敏感
compareJSON({
  baseJSON: { status: 'OK' },
  contrastJSON: { status: 'ok' },
  options: { valueCaseInsensitive: true },
});
// [](无差异)

各选项的详细说明请参阅对比选项

数组对比方法

import { compareJSON } from '@compare-json/core';

// 'byIndex'(默认)—— 按相同索引逐一对比
compareJSON({ baseJSON: [1, 2, 3], contrastJSON: [2, 3, 4] });

// 'lcs' —— 使用最长公共子序列算法,得到最小差异
compareJSON({
  baseJSON: [1, 2, 3],
  contrastJSON: [2, 3, 4],
  options: { arrayCompareMethod: 'lcs' },
});

// 'unordered' —— 将数组视为多重集合,忽略元素顺序
compareJSON({
  baseJSON: [1, 2, 3],
  contrastJSON: [3, 2, 1],
  options: { arrayCompareMethod: 'unordered' },
});
// [](无差异)

每种策略的深入讲解请参阅数组对比方法

格式化路径

import { pathSegmentsToString } from '@compare-json/core';

pathSegmentsToString(['users', '[0]', 'name']);
// 'users[0].name'

API 参考

compareJSON

function compareJSON(params: {
  baseJSON: unknown;
  contrastJSON: unknown;
  options?: CompareOptions;
}): JSONValueDifference[];

深度对比两个 JSON 值,返回差异数组。两个值相等时返回空数组。

参数类型说明
baseJSONunknown基准 JSON 值(视为原始一侧)。
contrastJSONunknown与基准对比的 JSON 值。
optionsCompareOptions可选的对比行为设置。

pathSegmentsToString

function pathSegmentsToString(pathSegments: string[]): string;

将路径片段数组(即 JSONValueDifference.pathSegments)转换为可读的点表示法字符串。数组索引片段(如 '[0]')不带前导点直接拼接;对象键用 . 连接。

pathSegmentsToString([]);                     // ''
pathSegmentsToString(['user', 'name']);       // 'user.name'
pathSegmentsToString(['items', '[2]', 'id']); // 'items[2].id'

CompareOptions

选项类型默认值说明
arrayCompareMethodArrayCompareMethod'byIndex'数组的对比策略。
keyCaseInsensitivebooleanfalsetrue 时,对象键按大小写不敏感方式对比。
valueCaseInsensitivebooleanfalsetrue 时,字符串值按大小写不敏感方式对比。
numericStringEqualsNumberbooleanfalsetrue 时,数字字符串视为与对应数字相等(如 "1" 等于 1)。

ArrayCompareMethod

type ArrayCompareMethod = 'byIndex' | 'lcs' | 'unordered';
说明
'byIndex'按相同索引逐一对比数组元素,多余的尾部元素报告为 added/deleted
'lcs'使用最长公共子序列算法,为有序数组检测最小差异。
'unordered'将数组视为多重集合,无论位置匹配相等元素。

JSONValueDiffType

type JSONValueDiffType = 'added' | 'deleted' | 'typeChanged' | 'valueChanged';
说明
'added'值存在于 contrastJSON 但不存在于 baseJSON
'deleted'值存在于 baseJSON 但不存在于 contrastJSON
'typeChanged'基准与对比值之间类型发生变化(如 numberstring)。
'valueChanged'类型不变但值发生变化。

JSONValueDifference

字段类型说明
pathSegmentsstring[]差异值的路径片段。对象键原样出现;数组索引以 '[n]' 形式出现(如 ['users', '[0]', 'name'])。
pathStringstring同一路径的点表示法字符串,数组索引保留为方括号后缀(如 'users[0].name')。
pathBelongsTo'base' | 'contrast' | 'both'路径所属一侧。deleted'base'added'contrast'valueChangedtypeChanged'both'
diffTypeJSONValueDiffType该路径检测到的差异类型。

许可证

MIT