GithubHelp home page GithubHelp logo

520mianxiangduixiang520 / json-diff Goto Github PK

View Code? Open in Web Editor NEW
15.0 2.0 0.0 2.13 MB

RFC 6902 的 Go 语言实现,An implementation of RFC6902 (https://tools.ietf.org/html/rfc6902) with Golang

License: Apache License 2.0

Go 100.00%
rfc-6902 diff json-diff unmarshal marshal

json-diff's Introduction

Json-Diff

RFC 6902 的 Go 语言实现

GoDoc

go get -u github.com/520MianXiangDuiXiang520/json-diff

功能:

序列化与反序列化

与官方 json 包的序列化和反序列化不同,官方包序列化需要指定一个 interface{}, 像:

package main

import "json"

func main() {
  jsonStr := "{}"
  var jsonObj interface{}
  node := json.Unmarshal(&jsonObj, []byte(jsonStr))
  // ...
}

这样不方便编辑反序列化后的 json 对象, json-diff 可以将任意的 json 串转换成统一的 JsonNode 类型,并且提供一系列的增删查改方法,方便操作对象:

func ExampleUnmarshal() {
    json := `{
        "A": 2,
        "B": [1, 2, 4],
        "C": {
          "CA": {"CAA": 1}
        }
      }`
    jsonNode := Unmarshal([]byte(json))
    fmt.Println(jsonNode)
}

差异比较

通过对比两个 Json 串,输出他们的差异或者通过差异串得到修改后的 json 串

func ExampleAsDiffs() {
	json1 := `{
        "A": 1,
        "B": [1, 2, 3],
        "C": {
          "CA": 1
        }
      }`
	json2 := `{
        "A": 2,
        "B": [1, 2, 4],
        "C": {
          "CA": {"CAA": 1}
        }
      }`
	res, _ := AsDiffs([]byte(json1), []byte(json2), UseMoveOption, UseCopyOption, UseFullRemoveOption)
	fmt.Println(res)
}
func ExampleMergeDiff() {
	json2 := `{
        "A": 1,
        "B": [1, 2, 3, {"BA": 1}],
        "C": {
          "CA": 1,
          "CB": 2
        }
      }`
	diffs := `[
        {"op": "move", "from": "/A", "path": "/D"},
        {"op": "move", "from": "/B/0", "path": "/B/1"},
        {"op": "move", "from": "/B/2", "path": "/C/CB"}
      ]`
	res, _ := MergeDiff([]byte(json2), []byte(diffs))
	fmt.Println(res)
}

输出格式

输出一个 json 格式的字节数组,类似于:

   [
     { "op": "test", "path": "/a/b/c", "value": "foo" },
     { "op": "remove", "path": "/a/b/c" },
     { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
     { "op": "replace", "path": "/a/b/c", "value": 42 },
     { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
     { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
   ]

其中数组中的每一项代表一个差异点,格式由 RFC 6902 定义,op 表示差异类型,有六种:

  1. add: 新增
  2. replace: 替换
  3. remove: 删除
  4. move: 移动
  5. copy: 复制
  6. test: 测试

其中 move 和 copy 可以减少差异串的体积,但会增加差异比较的时间, 可以通过修改 AsDiff() 的 options 指定是否开启,options 的选项和用法如下:

  // 返回差异时使用 Copy, 当发现新增的子串出现在原串中时,使用该选项可以将 Add 行为替换为 Copy 行为
  // 以减少差异串的大小,但这需要额外的计算,默认不开启
  UseCopyOption JsonDiffOption = 1 << iota

  // 仅在 UseCopyOption 选项开启时有效,替换前会添加 Test 行为,以确保 Copy 的路径存在
  UseCheckCopyOption

  // 返回差异时使用 Copy, 当发现差异串中两个 Add 和 Remove 的值相等时,会将他们合并为一个 Move 行为
  // 以此减少差异串的大小,默认不开启
  UseMoveOption

  // Remove 时除了返回 path, 还返回删除了的值,默认不开启
  UseFullRemoveOption

相等的依据

对于一个对象,其内部元素的顺序不作为相等判断的依据,如

{
  "a": 1,
  "b": 2,
}

{
  "b": 2,
  "a": 1,
}

被认为是相等的。

对于一个列表,元素顺序则作为判断相等的依据,如:

{
  "a": [1, 2]
}

{
  "a": [2, 1]
}

被认为不相等。

只有一个元素的所有子元素全部相等,他们才相等

原子性

根据 RFC 6092,差异合并应该具有原子性,即列表中有一个差异合并失败,之前的合并全部作废,而 test 类型就用来在合并差异之前检查路径和值是否正确,你可以通过选项开启它,但即便不使用 test,合并也是原子性的。

json-diff 在合并差异前会深拷贝源数据,并使用拷贝的数据做差异合并,一旦发生错误,将会返回 nil, 任何情况下都不会修改原来的数据。

参考

https://github.com/flipkart-incubator/zjsonpatch

json-diff's People

Contributors

520mianxiangduixiang520 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

json-diff's Issues

[BUG] json序列化和lcs计算好像有点问题

Describe the bug
感谢开源,比较了同类型的lib,您的实现性能是最好的。但是asdiff和lcs的测试貌似太少了,可以看下我贴出来的例子,这个比较典型,json序列化和lcs在下面的例子中都会报错

To Reproduce
you code:

json1 := `{"A": 1, "B": [1, 2, 3], "C": [1, 2]}`
json2 := `{"A": 1, "B": [1, 3], "C": [2, 1], "D": 6}`
AsDiffs([]byte(json1), []byte(json2), UseMoveOption, UseCopyOption, UseFullRemoveOption)

再次感谢您的开源!!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.