json規則引擎 golang

json格式還是現今web服務最常用的數據交換格式,有時需要對其字段進行篩選過濾和重組。
在github搜索,沒有發現合適的,於是自己寫了一個開源:https://github.com/sdghchj/rules_engine。

實現主過程要用到了go標準庫中的詞法分析包token和抽象語法樹包ast,略。

Example

Use rule engine by sql,only ‘select … from … where …’

    eng := NewJsonEngine(true)
    
    //sql keyword'case ingnored
    err := eng.ParseSql(`select "3" as a.a,'hello' as a.b,Sum(b.c) as a.c,Substr(c,2) as a.d,currenttimestamp() as a.e,* as a.f,b.f,b.c,b.c[2] + b.c[3] as b.b from aaa where a < 2 and b.c[4] = 5 and e.f = 2`)
    if err != nil {
        fmt.Println(err)
    }

    text := `{"a":1,"b":{"c":[1,2,3,4,5]},"c":"123456789","e":{"f":2}}`
    jsonText, err := eng.Convert("aaa",text)
     if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(jsonText))
    /*output
    {
        "a": {
            "a": "3",
            "b": "hello",
            "c": 15,
            "d": "3456",
            "e": 1556693661,
            "f": {
                "a": 1,
                "b": {
                    "c": [
                        1,
                        2,
                        3,
                        4,
                        5
                    ]
                },
                "c": "123456789",
                "e": {
                    "f": 2
                }
            }
        },
        "b": {
            "b": 7,
            "c": [
                1,
                2,
                3,
                4,
                5
            ]
        }
    }*/
    
    text = `{"a":5,"b":{"c":[6,5,4,3,2,1]},"c":"987654321"}`
    jsonText, err = eng.Convert("aaa",text)
     if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(jsonText)) // null

Use rule

    rule := rule.NewJsonRule(true)
    
    //query
    fieldFilter := filter.NewFieldFilter()
    fieldFilter.Parse("a < 2 && b.c[4] == 5 && e.f == 2")

    rule.AddConverter(fieldFilter)

    m := mapper.NewMapper()

    //select fields
    m.AddField("3", "a.a")
    m.AddField("'hello'", "a.b")
    m.AddField("Sum(b.c)", "a.c")
    m.AddField("Substr(c,2)", "a.d")
    m.AddCurrentTimestampField("a.e", nil)
    m.AddField("*", "a.f")
    m.AddField("b.c", "")
    m.AddField("b.c[2] + b.c[3]", "b.a")
    m.AddField("CurrentTimestamp()", "b.b")

    rule.AddConverter(m)
    
    text := `
            {
                "a":1,
                "b":{
                        "c":[1,2,3,4,5]
                    },
                "c":"123456789",
                "e":{
                        "f":2
                    }
            }
            `
    jsonText, _ := rule.Convert(text)
    
    fmt.Println(string(jsonText))
    /* 
        //output:
        {
            "a": {
                "a": 3,
                "b": "hello",
                "c": 15,
                "d": "3456789",
                "e": 1556611910,
                "f": {
                    "a": 1,
                    "b": {
                        "c": [
                            1,
                            2,
                            3,
                            4,
                            5
                        ]
                    },
                    "c": "123456789",
                    "e": {
                        "f": 2
                    }
                }
            },
            "b": {
                "a": 7,
                "b": 1556611910,
                "c": [
                    1,
                    2,
                    3,
                    4,
                    5
                ]
            }
        }
    */
    
    tm := time.Now()
    for i := 0; i < 10000; i ++  {
        _,_ = rule.Convert(text)
    }
    fmt.Println( "time elapse:",time.Now().Sub(tm).Nanoseconds(),"ns")
    /*
        //output:
        time elapse: 4265625000 ns
    */

Supported golang operators

    + - * / % && || ! > < == >= <= & | >> << [index]

Supported other operators in sql

   =    as  ==
   and  as  &&
   or   as  ||
   not  as  !

Supported functions (ignore case)

  • sum(array)
  • average(array)
  • len(array)
  • substr(text,pos,length)
  • currenttimestamp()
  • regex(text,pattern)
  • in(value,array)
  • abs(number)
  • exp(number)
  • sqrt(number)
  • power(numberX,numberY)
  • ceil(number)
  • floor(number)
  • iif(condition,whenTrue,whenFalse)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章