spyzhov / ajson

Abstract JSON for Golang with JSONPath support
MIT License
247 stars 23 forks source link

Version v1.0.0 #42

Open spyzhov opened 3 years ago

spyzhov commented 3 years ago

Draft for the Version v1.0.0 milestone

  1. Create sub-package ajson/jsonpath with the main types and functions:

    package jsonpath
    
    type JSONPath struct {
      Tokens []Token
    }
    type Token interface {
      ...
    }
    var _ Token = (*JSONPath)(nil)
    
    func Compile(jsonpath string) (*JSONPath, error)
    func MustCompile(jsonpath string) *JSONPath

    Add changes in the main package:

    package ajson
    
    func JSONPathApply(*Node, *jsonpath.JSONPath, ...Options) ([Nodes, error)
    • create all necessary Token types
    • add an ability to use array and object types
    • think about variables with placeholders for it
  2. Segregation for types and packages.
    • think about jmath;
    • move all system parts in the internal package;
  3. Remove threadsafe part, as it is unused.
  4. Add public interfaces:

    • for typed Node, such as StringNode, ArrayNode, etc.
    • IterableNode interface for ArrayNode and ObjectNode
    • for []*Node add alias type Nodes []Node

      type Nodes []Node
      func (n Nodes) First() Node
      func (n Nodes) Last() Node
      func (n Nodes) Error() error // ???
      func (n Nodes) JSONPath(...) (Nodes, error)
      func (n Nodes) Clone() Nodes
      func (n Nodes) Size() int
      
      func (n Nodes) Map(func (*Node) *Node) Nodes
      func (n Nodes) Filter(func (*Node) bool) Nodes
      
      JSONPath(...) (Nodes, error)
  5. Add a fake type Date (discussed)

    type Date (String)
    
    fun date(string|numeric, format) Date
    fun now() Date
    
    # usage:
    $..[?(date(@.timestamp) > now())]
    $..[?(date(@.timestamp) + date("1 hour", "%H hour") < now())]
  6. Add functional methods

    Chain(Node, ...func(Node) (Node, error) ... ) (Node, error)
    
    Filter(Node, func(Node) bool) (Node, error)
    Map(Node, func(Node) (Node, error)) (Node, error)
    Reduce...
    
    All(Node) bool
    Any(Node) bool
  7. Math:
    • Add additional jsonb operators from https://www.postgresql.org/docs/9.5/functions-json.html
    • Change Funtion type to:
      type Function func(node ...*Node) (result *Node, err error)
    • think about function: not => !@.length
    • add math functions:
      first(node ...*Node) *Node
      get(index_or_key String|Integer, node ...*Node) *Node
    • add operator in => value in [array]
    • add functions max(array|object), min(array|object), avg(array|object).
  8. Add Buffer interface, which could be based on (1) []byte and (2) io.Readable interface;
  9. Add JSONPATH config values, like:
    • AllowScript to allow using !() outside of the filter section;
    • SpecificationVersion
    • etc.
  10. CLI:
    • Add support for multiline JSON. Flag -m/-multiline. Example: JSON logs in Docker.
      docker logs service | ajson -m "$.[?(@.level = 'error')]"
    • Add support for stream JSON. Flag -f/-stream. It will do the output as soon as the value was found.
    • Add pretty print support. Flag -pretty
    • Add suttort to remove given pattern from the result. Flag -reverse/-r
  11. Mutations:
    • Think about to add lock function and lock nodes on modifications.
      func (n Node) Set(value interface{}) error {
         defer lock(n).unlock()
         // todo
      }

      Use it for root (if needed)

      func (n Node) Set(value interface{}) error {
         defer lock(n.root()).unlock()
         // todo
      }
    • Add an Option to create a *Node if it was not found during the JSONPath execution. Example:
      nodes, _ := root.JSONPath(`$.foo.bar`, ajson.FindOrCreate)

      With the given json value {} the result output for the root will be {"foo":{"bar":null}}

  12. Documentation:
    • README.md
    • Examples
    • Add Wiki pages
    • readthedocs.io
iamtheschmitzer commented 2 years ago

@spyzhov Does this include #12 the additional jsonb operators ?

spyzhov commented 2 years ago

@iamtheschmitzer, Yes. I'm going to implement it.

bjoerndemeyer commented 2 years ago

Is there any way we can help you with this? I would like to use this library and v1 would be great.

spyzhov commented 2 years ago

I'd like to, but right now I'm not sure if it is possible. I will try to split this issue later.