Golang Json content addition, deletion and modification based on JSONPath

1. Background and Objectives

Try developing a generic go_jsonpath library ( code.byted.org/temai/go\_j…

  • Get/MGet: query for the specified node element value

  • Set: Specifies the insertion of the node element value

  • Delete: delete the specified node element value

  • Sort: Specifies the sorting of the list of node elements

2. Status of Json library

Investigating some common json libs at present, no ideal ones were found. The details are as follows:

lib illustrate example
encoding/json Go's built-in JSON encoding and decoding (serialization and deserialization) -
josephburnett/jd/lib json diff image
oliveagle/jsonpath Node element query based on JSONPath image
tidwall / sjson Based on the custom dot syntax, set the value of the specified node element. image
{ "name": {"first": "Tom", "last": "Anderson"}, "age":37, "children": ["Sara","Alex","Jack"], "fav.movie": "Deer Hunter", "friends": [ {"first": "James", "last": "Murphy"}, {"first": "Roger", "last": "Craig"} ] }

Three. go_jsonpath

go_jsonpath(code.byted.org/temai/go\_j…

3.1 jsonpath介绍

JSONPath 之于 JSON,就如 XPath 之于 XML。JSONPath 可以方便对 JSON 数据结构进行内容提取(goessner.net/articles/Js…

比如,下面Json

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

对应的jsonpath:

3.2 规则引擎govaluate介绍

规则引擎govaluate与 JavaScript 中的eval功能类似,用于计算任意表达式的值,详细用法参考github.com/Knetic/gova…

func main() {
  expr, _ := govaluate.NewEvaluableExpression("foo > 0")
  parameters := make(map[string]interface{})
  parameters["foo"] = -1
  result, _ := expr.Evaluate(parameters)
  fmt.Println(result)

  expr, _ = govaluate.NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90")
  parameters = make(map[string]interface{})
  parameters["requests_made"] = 100
  parameters["requests_succeeded"] = 80
  result, _ = expr.Evaluate(parameters)
  fmt.Println(result)

  expr, _ = govaluate.NewEvaluableExpression("(mem_used / total_mem) * 100")
  parameters = make(map[string]interface{})
  parameters["total_mem"] = 1024
  parameters["mem_used"] = 512
  result, _ = expr.Evaluate(parameters)
  fmt.Println(result)
}

3.3 go_jsonpath介绍

  • 接口介绍
方法 用法 说明
get Get(path string) (val interface{}, err error) 获取指定jsonpath
set Set(path string, value interface{}) (err error) 更改指定jsonpath,key不存在时自动创建
delete Delete(path string) (err error) 删除指定jsonpath
extract Extract(path string, extractType ExtractTypeEnum) (err error) 将复杂jsonpath值(url/json等)展开成结构化数据
ab_delete abDelete() (err error) 两个结构相同json匹配某种规则时,删除指定jsonpath
  • 详细用法

比如,下面json

{
  "promotions":[
    {
      "product_id":"123",
      "type":1
    },
    {
      "product_id":"456",
      "type":2
    }
  ],
  "extra":{
    "logid":"20000000000000000000000000"
  },
  "entries":[
    {
      "title":"咨询",
      "type":1
    },
    {
      "title":"订单",
      "type":2
    }
  ],
  "status_code":0,
  "status_msg":""
}

处理逻辑

func TestGoJsonPath_Executor(t *testing.T)  {
   ctx := context.Background()
   jf, err := os.Open(FromJson)
   if err != nil {
      t.Fatal(err.Error())
   }
   jv, err := ioutil.ReadAll(jf)
   if err != nil {
      t.Fatal(err.Error())
   }
   h, err := executor.NewExecutor(ctx, string(jv))
   if err != nil {
      t.Fatal(err.Error())
   }
   // 1. Set,Get
   _ = h.Set("$.promotions[0].product_id", "5")
   val, _ := h.Get("$.promotions[0].product_id")
   assert.Equal(t, val, "5")
   // 2. Sort,MGet
   _ = h.Sort("$.entries", "get([v1], 'type') > get([v2], 'type')")
   _, vals := h.MGet("$.entries[*].type")
   assert.Equal(t, vals[0].(float64) > vals[1].(float64), true)
   // 3. Delete
   val, _ = h.Get("$.extra.logid")
   assert.Equal(t, val, "20000000000000000000000000")
   _ = h.Delete("$.extra.logid")
   val, _ = h.Get("$.extra.logid")
   assert.Equal(t, val, nil)
}

Guess you like

Origin juejin.im/post/7120503723205328926