头图

foreword

In the previous article , I introduced the features of xjson and the quick and easy access to the value in JSON using query syntax.

At the same time, this time also updated a version, mainly two upgrades:

  1. Support for escape characters.
  2. Performance optimization, about 30% improvement⬆️.

escape character

Let’s talk about the first escape character first, whether it is the original JSON escape character in the string or the escape character in the query syntax has been supported, the specific usage is as follows:

 str = `{"1a.b.[]":"b"}`
    get = Get(str, "1a\\.b\\.\\[\\]")
    assert.Equal(t, get.String(), "b")

    str = `{".":"b"}`
    get = Get(str, "\\.")
    assert.Equal(t, get.String(), "b")

    str = `{"a":"{\"a\":\"123\"}"}`
    get = Get(str, "a")
    fmt.Println(get)
    assert.Equal(t, get.String(), "{\"a\":\"123\"}")
    assert.Equal(t, Get(get.String(), "a").String(), "123")

    str = `{"a":"{\"a\":[1,2]}"}`
    get = Get(str, "a")
    fmt.Println(get)
    assert.Equal(t, get.String(), "{\"a\":[1,2]}")
    assert.Equal(t, Get(get.String(), "a[0]").Int(), 1)

performance optimization

The performance has also been partially optimized, which is about 30% higher than the previous version.

 pkg: github.com/crossoverJie/xjson/benckmark
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkDecode-12               14968         77130 ns/op       44959 B/op        1546 allocs/op
PASS

------------------------------------
pkg: github.com/crossoverJie/xjson/benckmark
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkDecode-12               19136         62960 ns/op       41593 B/op        1407 allocs/op
PASS

But in general, there is still a lot of room for optimization, mainly because the upper limit is low after all, and there is still a big gap with the official library ratio.

implement four operations

Next, let's talk about how the four operations are implemented, which is quite interesting in itself feature , although there are not many scenes used 🙂.

Let's take a look at how it is used:

 json :=`{"alice":{"age":10},"bob":{"age":20},"tom":{"age":20}}`
    query := "(alice.age+bob.age) * tom.age"
    arithmetic := GetWithArithmetic(json, query)
    assert.Equal(t, arithmetic.Int(), 600)

Enter a JSON string and calculation formula and get the calculation result.

In fact, the implementation principle is relatively simple, and it is divided into three steps:

  1. Perform lexical analysis on json , and get the first step of a four arithmetic operation token .
  2. Based on the token stream, the final four arithmetic expressions are produced, such as (3+2)*5
  3. Call the four arithmetic processors to get the final result.

Look at the first step first, according to (alice.age+bob.age) * tom.age parse out token :

The second step is to parse the token, and parse it into specific data when it encounters the Identifier type.

For other types of tokens, you can directly concatenate strings, and finally generate an expression: (10+20)*20

The core functionality of this step is provided by the xjson.Get(json, query) function.

The key code is shown below:

The ultimate purpose is to be able to generate an expression, as long as you get the four arithmetic expressions, you can get the final calculation result.

The final calculation logic is actually quite simple. Build an AST tree, and then traverse the recursive solution in depth, as shown in the following figure:

The core functionality of this step is provided by the previously implemented script interpreter gscipt .

Interested friends can view the source code.

Summarize

A JSON library does not have many functions. You are welcome to share the commonly used functions of the JSON library; you are also welcome to experience this library.

Source address:
https://github.com/crossoverJie/xjson


crossoverJie
5.4k 声望4k 粉丝