leptjson

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2025 License: MIT Imports: 7 Imported by: 0

README

从零开始的 JSON 库教程(十三):JSON Patch 实现

JSON Patch 简介

JSON Patch 是一种用于描述 JSON 文档修改的格式,定义在 RFC 6902 中。它提供了一种标准化的方式来表示对 JSON 文档的操作,如添加、删除、替换、移动或复制值,以及测试值是否存在或匹配预期。

JSON Patch 文档是一个 JSON 数组,每个元素都是一个表示单个操作的对象。每个操作对象至少有两个成员:

  • op: 操作类型,如 "add"、"remove"、"replace"、"move"、"copy" 或 "test"
  • path: 一个 JSON Pointer,指定要操作的目标位置

根据操作类型的不同,还可能需要其他字段,如:

  • value: 用于 "add"、"replace" 或 "test" 操作
  • from: 用于 "move" 或 "copy" 操作,指定源位置

操作类型

1. add

将值添加到对象或数组。对于数组,索引可以是"-"表示在数组末尾添加。

{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
2. remove

从对象或数组中移除值。

{ "op": "remove", "path": "/a/b/c" }
3. replace

替换值。

{ "op": "replace", "path": "/a/b/c", "value": 42 }
4. move

将值从一个位置移动到另一个位置。

{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
5. copy

从一个位置复制值到另一个位置。

{ "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
6. test

测试值是否等于提供的值。

{ "op": "test", "path": "/a/b/c", "value": "foo" }

使用示例

假设我们有一个 JSON 文档:

{
  "biscuits": [
    { "name": "Digestive" },
    { "name": "Choco Leibniz" }
  ]
}

我们可以应用以下 JSON Patch:

[
  { "op": "add", "path": "/biscuits/1", "value": { "name": "Ginger Nut" } },
  { "op": "remove", "path": "/biscuits/0" },
  { "op": "replace", "path": "/biscuits/0/name", "value": "Chocolate Digestive" },
  { "op": "copy", "from": "/biscuits/0", "path": "/best_biscuit" }
]

应用后,JSON 文档将变为:

{
  "biscuits": [
    { "name": "Chocolate Digestive" }
  ],
  "best_biscuit": { "name": "Chocolate Digestive" }
}

本章实现目标

在本章中,我们将实现一个符合 RFC 6902 的 JSON Patch 处理器,支持以下功能:

  1. 解析 JSON Patch 文档
  2. 验证 Patch 操作的有效性
  3. 应用 Patch 到 JSON 文档
  4. 生成两个文档之间的差异作为 JSON Patch

此外,我们还将在下一章实现 JSON Merge Patch(RFC 7396),它是一种更简单但功能较弱的 JSON 文档修改方法。

实现计划

  1. 创建基本的 JSON Patch 数据结构
  2. 实现解析 JSON Patch 文档的功能
  3. 实现各种操作类型的处理逻辑
  4. 添加错误处理和验证
  5. 实现生成 Patch 的功能
  6. 完善文档和示例

JSON Patch vs JSON Merge Patch

JSON Patch 和 JSON Merge Patch 是两种不同的 JSON 文档修改方法:

  • JSON Patch:更详细和精确,支持多种操作类型,适合复杂的修改。
  • JSON Merge Patch:更简单直观,但功能较弱,主要用于简单的更新操作。

在本章我们将实现 JSON Patch,在下一章将实现 JSON Merge Patch,以提供完整的 JSON 修改能力。

参考资料

Documentation

Overview

cycle_detection.go - 循环引用检测实现

json_patch.go - JSON Patch 实现 (RFC 6902)

json_path.go - JSON Path 实现

json_pointer.go - JSON指针实现 (RFC6901)

json_schema.go - JSON Schema 验证实现(基于部分 JSON Schema Draft 7)

leptjson.go - Go语言版JSON库

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildJSONPointer

func BuildJSONPointer(segments ...interface{}) (string, error)

BuildJSONPointer 创建一个JSON指针字符串

func ClearArray

func ClearArray(v *Value)

ClearArray 清空数组的所有元素

func ClearObject

func ClearObject(v *Value)

ClearObject 清空对象的所有成员

func Copy

func Copy(dst, src *Value)

Copy 深度复制一个JSON值

func CopySafe

func CopySafe(dst, src *Value) error

CopySafe 安全复制JSON值,避免循环引用

func CopySafeWithReplacement

func CopySafeWithReplacement(dst, src *Value)

CopySafeWithReplacement 带替换的安全复制

func CustomCopySafeWithReplacement

func CustomCopySafeWithReplacement(dst, src *Value, replacer CircularReplacer)

CustomCopySafeWithReplacement 使用自定义替换器的安全复制

func Equal

func Equal(lhs, rhs *Value) bool

Equal 判断两个JSON值是否相等

func EraseArrayElement

func EraseArrayElement(v *Value, index, count int)

EraseArrayElement 删除数组中从index开始的count个元素

func FindObjectIndex

func FindObjectIndex(v *Value, key string) int

FindObjectIndex 查找JSON对象中指定键的索引

func Free

func Free(v *Value)

Free 释放JSON值占用的资源

func GetArrayCapacity

func GetArrayCapacity(v *Value) int

GetArrayCapacity 获取数组当前的容量

func GetArraySize

func GetArraySize(v *Value) int

GetArraySize 获取JSON数组的大小

func GetBoolean

func GetBoolean(v *Value) bool

GetBoolean 获取JSON布尔值

func GetErrorMessage

func GetErrorMessage(code ParseError) string

GetErrorMessage 根据错误码获取错误消息

func GetNumber

func GetNumber(v *Value) float64

GetNumber 获取JSON数字值

func GetObjectCapacity

func GetObjectCapacity(v *Value) int

GetObjectCapacity 获取对象的容量

func GetObjectKey

func GetObjectKey(v *Value, index int) string

GetObjectKey 获取JSON对象的键

func GetObjectSize

func GetObjectSize(v *Value) int

GetObjectSize 获取JSON对象的大小

func GetString

func GetString(v *Value) string

GetString 获取JSON字符串值

func HasCycle

func HasCycle(v *Value) bool

HasCycle 检测JSON值中是否存在循环引用

func Move

func Move(dst, src *Value)

Move 将源值移动到目标值,并将源值设为null

func ParseJSONPointer

func ParseJSONPointer(pointer string) (*JSONPointer, JSONPointerError)

ParseJSONPointer 解析JSON指针字符串 例如: "/foo/0/bar" => ["foo", "0", "bar"]

func PopBackArrayElement

func PopBackArrayElement(v *Value)

PopBackArrayElement 移除数组末尾的元素

func RemoveObjectValue

func RemoveObjectValue(v *Value, index int)

RemoveObjectValue 移除对象中指定索引的成员

func RemoveValueByPointer

func RemoveValueByPointer(v *Value, pointerStr string) error

RemoveValueByPointer 使用JSON指针删除值

func ReserveArray

func ReserveArray(v *Value, capacity int)

ReserveArray 扩充数组容量

func ReserveObject

func ReserveObject(v *Value, capacity int)

ReserveObject 扩充对象容量

func SafeCopyWithReplacer

func SafeCopyWithReplacer(dst, src *Value, replacer CircularReplacer)

SafeCopyWithReplacer 带替换器的安全复制,处理循环引用

func SetArray

func SetArray(v *Value, capacity int)

SetArray 设置值为数组类型,可以预分配容量

func SetBoolean

func SetBoolean(v *Value, b bool)

SetBoolean 设置JSON布尔值

func SetNull

func SetNull(v *Value)

SetNull 将值设置为NULL类型

func SetNumber

func SetNumber(v *Value, n float64)

SetNumber 设置JSON数字值

func SetObject

func SetObject(v *Value)

SetObject 设置值为对象类型,可以预分配容量

func SetString

func SetString(v *Value, s string)

SetString 设置JSON字符串值

func SetValueByPointer

func SetValueByPointer(v *Value, pointerStr string, value *Value) error

SetValueByPointer 使用JSON指针设置值

func ShrinkArray

func ShrinkArray(v *Value)

ShrinkArray 缩小数组容量至实际大小

func ShrinkObject

func ShrinkObject(v *Value)

ShrinkObject 缩小对象容量至实际大小

func Swap

func Swap(lhs, rhs *Value)

Swap 交换两个JSON值

Types

type CircularReplacer

type CircularReplacer func(path []string) *Value

CircularReplacer 定义了在发现循环引用时的替换函数类型

type CycleError

type CycleError int

CycleError 表示循环引用错误

const (
	CYCLE_OK CycleError = iota
	CYCLE_DETECTED
)

循环引用错误常量

func DetectCycle

func DetectCycle(v *Value) CycleError

DetectCycle 检测JSON值中是否存在循环引用

func SafeCopy

func SafeCopy(dst, src *Value) CycleError

SafeCopy 安全复制JSON值,检测并处理循环引用

func (CycleError) Error

func (e CycleError) Error() string

实现 Error 接口

type EnhancedError

type EnhancedError struct {
	Code          ParseError // 错误码
	Message       string     // 错误消息
	Line          int        // 行号
	Column        int        // 列号
	Context       string     // 错误发生的上下文
	Pointer       string     // 错误位置指针(比如 "----^")
	SourceInput   string     // 输入源
	IsRecoverable bool       // 是否可恢复
}

EnhancedError 定义了一个增强的错误类型,包含详细信息

func (*EnhancedError) Error

func (e *EnhancedError) Error() string

Error 实现error接口

type JSONPatch

type JSONPatch struct {
	Operations []PatchOperation // 操作列表
}

JSONPatch 表示一个 JSON Patch 文档,包含多个操作

func CreatePatch

func CreatePatch(source, target *Value) (*JSONPatch, error)

CreatePatch 生成从 source 到 target 的 JSON Patch

func NewJSONPatch

func NewJSONPatch(patchDoc *Value) (*JSONPatch, error)

NewJSONPatch 从 JSON 值中创建 JSON Patch 对象

func NewJSONPatchFromString

func NewJSONPatchFromString(patchStr string) (*JSONPatch, error)

NewJSONPatchFromString 从 JSON 字符串创建 JSON Patch 对象

func (*JSONPatch) Apply

func (p *JSONPatch) Apply(doc *Value) error

Apply 将 JSON Patch 应用到文档

func (*JSONPatch) String

func (p *JSONPatch) String() (string, error)

String 返回 JSON Patch 的字符串表示

type JSONPath

type JSONPath struct {
	Path   string  // 原始路径表达式
	Tokens []Token // 令牌列表
}

JSONPath 表示一个解析后的 JSON Path 表达式

func NewJSONPath

func NewJSONPath(path string) (*JSONPath, error)

NewJSONPath 解析 JSON Path 表达式并创建一个 JSONPath 对象

func (*JSONPath) Query

func (jp *JSONPath) Query(doc *Value) ([]*Value, error)

Query 使用 JSON Path 查询 JSON 值并返回匹配的值列表

func (*JSONPath) QueryOne

func (jp *JSONPath) QueryOne(doc *Value) (*Value, error)

QueryOne 返回第一个匹配的值,如果没有匹配则返回 nil

type JSONPathError

type JSONPathError struct {
	Path    string // JSON Path 表达式
	Message string // 错误消息
	Index   int    // 错误发生的位置
}

JSONPathError 表示解析或执行 JSON Path 时的错误

func (JSONPathError) Error

func (e JSONPathError) Error() string

Error 实现 error 接口

type JSONPointer

type JSONPointer struct {
	// contains filtered or unexported fields
}

JSONPointer 表示一个JSON指针(RFC6901)

func GetJSONPointer

func GetJSONPointer(segments ...interface{}) (*JSONPointer, error)

GetJSONPointer 创建一个指向指定路径的JSONPointer 例如: NewJSONPointer("foo", 0, "bar") => "/foo/0/bar"

func (*JSONPointer) Get

func (p *JSONPointer) Get(root *Value) (*Value, JSONPointerError)

Get 根据JSON指针获取值

func (*JSONPointer) Insert

func (p *JSONPointer) Insert(root *Value, value *Value) JSONPointerError

Insert 根据JSON指针在数组中插入值或在对象中添加/替换值 对于数组,支持索引插入和末尾追加 ("-")

func (*JSONPointer) Remove

func (p *JSONPointer) Remove(root *Value) JSONPointerError

Remove 根据JSON指针删除值

func (*JSONPointer) Replace

func (p *JSONPointer) Replace(root *Value, value *Value) JSONPointerError

Replace 根据JSON指针替换现有值或添加对象成员 注意:对于数组,此方法执行替换,不执行插入。

func (*JSONPointer) String

func (p *JSONPointer) String() string

创建一个JSON指针字符串表示

type JSONPointerError

type JSONPointerError int

JSONPointerError 表示JSON指针相关错误

const (
	POINTER_OK JSONPointerError = iota
	POINTER_INVALID_FORMAT
	POINTER_INDEX_OUT_OF_RANGE
	POINTER_KEY_NOT_FOUND
	POINTER_INVALID_TARGET
)

JSON指针错误常量

func (JSONPointerError) Error

func (e JSONPointerError) Error() string

实现 Error 接口

type JSONSchema

type JSONSchema struct {
	Schema *Value // 存储 JSON Schema 的 Value 对象
}

JSONSchema 表示一个 JSON Schema 对象

func NewJSONSchema

func NewJSONSchema(schemaJSON string) (*JSONSchema, error)

NewJSONSchema 创建一个新的 JSON Schema

func NewJSONSchemaFromValue

func NewJSONSchemaFromValue(schema *Value) (*JSONSchema, error)

NewJSONSchemaFromValue 从 Value 对象创建 JSON Schema

func (*JSONSchema) Validate

func (js *JSONSchema) Validate(data *Value) *SchemaValidationResult

Validate 根据 Schema 验证 JSON 数据

type Member

type Member struct {
	K string // 键
	V *Value // 值
}

Member 表示对象的成员(键值对)

type ParseError

type ParseError int

ParseError 表示解析错误

const (
	PARSE_OK                           ParseError = iota // 解析成功
	PARSE_EXPECT_VALUE                                   // 期望一个值
	PARSE_INVALID_VALUE                                  // 无效的值
	PARSE_ROOT_NOT_SINGULAR                              // 根节点不唯一
	PARSE_NUMBER_TOO_BIG                                 // 数字太大
	PARSE_MISS_QUOTATION_MARK                            // 缺少引号
	PARSE_INVALID_STRING_ESCAPE                          // 无效的转义序列
	PARSE_INVALID_STRING_CHAR                            // 无效的字符
	PARSE_INVALID_UNICODE_HEX                            // 无效的Unicode十六进制
	PARSE_INVALID_UNICODE_SURROGATE                      // 无效的Unicode代理对
	PARSE_MISS_COMMA_OR_SQUARE_BRACKET                   // 缺少逗号或方括号
	PARSE_MISS_KEY                                       // 缺少键
	PARSE_MISS_COLON                                     // 缺少冒号
	PARSE_MISS_COMMA_OR_CURLY_BRACKET                    // 缺少逗号或花括号
	PARSE_MAX_DEPTH_EXCEEDED                             // 超过最大嵌套深度
	PARSE_COMMENT_NOT_CLOSED                             // 注释未闭合
)

解析错误常量

func Parse

func Parse(v *Value, json string) ParseError

Parse 解析JSON文本(使用默认选项)

func ParseWithOptions

func ParseWithOptions(v *Value, json string, options ParseOptions) ParseError

ParseWithOptions 使用自定义选项解析JSON文本

解析步骤: 1. 跳过前导空白字符 2. 解析JSON值 3. 跳过后续空白字符 4. 检查是否还有额外内容(这将导致PARSE_ROOT_NOT_SINGULAR错误)

func (ParseError) Error

func (e ParseError) Error() string

Error 返回解析错误的描述

type ParseOptions

type ParseOptions struct {
	MaxDepth          int  // 最大嵌套深度
	AllowComments     bool // 是否允许注释
	AllowTrailing     bool // 是否允许尾随逗号
	StrictMode        bool // 严格模式(更严格的检查)
	RecoverFromErrors bool // 是否从非致命错误恢复
}

ParseOptions 定义解析选项

func DefaultParseOptions

func DefaultParseOptions() ParseOptions

DefaultParseOptions 返回默认解析选项

type PatchError

type PatchError struct {
	Operation string // 发生错误的操作类型
	Path      string // 发生错误的路径
	Message   string // 错误消息
}

PatchError 表示 JSON Patch 操作中的错误

func (PatchError) Error

func (e PatchError) Error() string

Error 实现 error 接口

type PatchOperation

type PatchOperation struct {
	Op    string // 操作类型: add, remove, replace, move, copy, test
	Path  string // 操作的目标路径 (JSON Pointer)
	From  string // 源路径 (用于 move 和 copy 操作)
	Value *Value // 值 (用于 add, replace 和 test 操作)
}

PatchOperation 表示 JSON Patch 中的单个操作

type SchemaValidationError

type SchemaValidationError struct {
	Path    string // 导致错误的 JSON 路径
	Message string // 错误描述
}

SchemaValidationError 表示 JSON Schema 验证错误

func (SchemaValidationError) Error

func (e SchemaValidationError) Error() string

实现 Error 接口

type SchemaValidationResult

type SchemaValidationResult struct {
	Valid  bool                    // 是否验证通过
	Errors []SchemaValidationError // 验证错误列表
}

SchemaValidationResult 存储验证结果

func (*SchemaValidationResult) AddError

func (r *SchemaValidationResult) AddError(path, message string)

AddError 添加验证错误

type SliceInfo

type SliceInfo struct {
	Start int
	End   int
	Step  int
}

SliceInfo 存储数组切片信息

type StringifyError

type StringifyError int

StringifyError 表示字符串化错误

const (
	STRINGIFY_OK StringifyError = iota // 字符串化成功
)

字符串化错误常量

func Stringify

func Stringify(v *Value) (string, StringifyError)

Stringify 将Value转换为JSON字符串

func (StringifyError) Error

func (e StringifyError) Error() string

Error 返回字符串化错误的描述

type Token

type Token struct {
	Type  TokenType // 令牌类型
	Value string    // 令牌值
}

Token 表示 JSON Path 中的一个令牌

type TokenType

type TokenType int

TokenType 表示 JSON Path 令牌的类型

const (
	ROOT              TokenType = iota // $ - 根节点
	CURRENT                            // @ - 当前节点
	DOT                                // . - 子属性访问
	RECURSIVE_DESCENT                  // .. - 递归下降
	WILDCARD                           // * - 通配符
	BRACKET_START                      // [ - 下标访问开始
	BRACKET_END                        // ] - 下标访问结束
	INDEX                              // 数字索引
	PROPERTY                           // 属性名
	SLICE                              // 切片 [start:end:step]
	UNION                              // 并集 [expr,expr]
	FILTER                             // ?() - 过滤器
)

type Value

type Value struct {
	Type ValueType `json:"type"` // 值类型
	N    float64   `json:"n"`    // 数字值(当Type为NUMBER时有效)
	S    string    `json:"s"`    // 字符串值(当Type为STRING时有效)
	A    []*Value  `json:"a"`    // 数组值(当Type为ARRAY时有效)
	O    []Member  `json:"o"`    // 对象值(当Type为OBJECT时有效)
}

Value 表示一个JSON值

func DefaultCircularReplacer

func DefaultCircularReplacer(path []string) *Value

DefaultCircularReplacer 默认循环引用替换器

func FindObjectKey

func FindObjectKey(v *Value, key string) (*Value, bool)

FindObjectKey 根据键名在对象中查找对应值,如果找到返回值和true,否则返回nil和false

func GetArrayElement

func GetArrayElement(v *Value, index int) *Value

GetArrayElement 获取JSON数组的元素

func GetObjectValue

func GetObjectValue(v *Value, index int) *Value

GetObjectValue 获取JSON对象的值

func GetObjectValueByKey

func GetObjectValueByKey(v *Value, key string) *Value

GetObjectValueByKey 根据键获取JSON对象的值

func GetValueByPointer

func GetValueByPointer(v *Value, pointerStr string) (*Value, error)

GetValueByPointer 使用JSON指针获取值

func InsertArrayElement

func InsertArrayElement(v *Value, index int) *Value

InsertArrayElement 在指定位置插入元素,并返回该元素

func PushBackArrayElement

func PushBackArrayElement(v *Value) *Value

PushBackArrayElement 在数组末尾添加一个新元素,并返回该元素

func QueryOneString

func QueryOneString(doc *Value, path string) (*Value, error)

QueryOneString 是一个便捷函数,返回匹配路径的第一个值

func QueryString

func QueryString(doc *Value, path string) ([]*Value, error)

QueryString 是一个便捷函数,直接使用路径表达式查询 JSON 值

func SetObjectValue

func SetObjectValue(v *Value, key string) *Value

SetObjectValue 设置对象的键值对,如果键已存在则返回其值指针,否则添加新的键值对并返回新值指针

func (Value) String

func (v Value) String() string

String 返回Value的字符串表示

type ValueType

type ValueType int

ValueType 表示JSON值的类型

const (
	NULL ValueType = iota
	FALSE
	TRUE
	NUMBER
	STRING
	ARRAY
	OBJECT
)

JSON值类型常量

func GetType

func GetType(v *Value) ValueType

GetType 获取JSON值的类型

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL