github.com/mithrandie/csvq@v1.18.1/lib/json/query.go (about)

     1  package json
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/mithrandie/csvq/lib/value"
     8  
     9  	"github.com/mithrandie/go-text/json"
    10  )
    11  
    12  func LoadValue(queryString string, jsontext string) (value.Primary, error) {
    13  	structure, _, err := load(queryString, jsontext)
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  
    18  	return ConvertToValue(structure), nil
    19  }
    20  
    21  func LoadArray(queryString string, jsontext string) ([]value.Primary, error) {
    22  	structure, _, err := load(queryString, jsontext)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	array, ok := structure.(json.Array)
    28  	if !ok {
    29  		return nil, errors.New(fmt.Sprintf("json value does not exists for %q", queryString))
    30  	}
    31  
    32  	return ConvertToArray(array), nil
    33  }
    34  
    35  func LoadTable(queryString string, jsontext string) ([]string, [][]value.Primary, json.EscapeType, error) {
    36  	structure, et, err := load(queryString, jsontext)
    37  	if err != nil {
    38  		return nil, nil, et, err
    39  	}
    40  
    41  	array, ok := structure.(json.Array)
    42  	if !ok {
    43  		return nil, nil, et, errors.New(fmt.Sprintf("json value does not exists for %q", queryString))
    44  	}
    45  
    46  	h, rows, err := ConvertToTableValue(array)
    47  	return h, rows, et, err
    48  }
    49  
    50  func load(queryString string, jsontext string) (json.Structure, json.EscapeType, error) {
    51  	query, err := Query.Parse(queryString)
    52  	if err != nil {
    53  		return nil, 0, err
    54  	}
    55  
    56  	d := json.NewDecoder()
    57  	d.UseInteger = false
    58  	data, et, err := d.Decode(jsontext)
    59  	if err != nil {
    60  		return nil, et, err
    61  	}
    62  
    63  	st, err := Extract(query, data)
    64  	return st, et, err
    65  }
    66  
    67  func Extract(query QueryExpression, data json.Structure) (json.Structure, error) {
    68  	var extracted json.Structure
    69  	var err error
    70  
    71  	if query == nil {
    72  		return data, nil
    73  	}
    74  
    75  	switch query.(type) {
    76  	case Element:
    77  		switch data.(type) {
    78  		case json.Object:
    79  			element := query.(Element)
    80  
    81  			obj := data.(json.Object)
    82  			if obj.Exists(element.Label) {
    83  				if element.Child == nil {
    84  					extracted = obj.Value(element.Label)
    85  				} else {
    86  					extracted, err = Extract(element.Child, obj.Value(element.Label))
    87  				}
    88  			} else {
    89  				extracted = json.Null{}
    90  			}
    91  		default:
    92  			extracted = json.Null{}
    93  		}
    94  	case ArrayItem:
    95  		switch data.(type) {
    96  		case json.Array:
    97  			arrayItem := query.(ArrayItem)
    98  
    99  			ar := data.(json.Array)
   100  			if arrayItem.Index < len(ar) {
   101  				if arrayItem.Child == nil {
   102  					extracted = ar[arrayItem.Index]
   103  				} else {
   104  					extracted, err = Extract(arrayItem.Child, ar[arrayItem.Index])
   105  				}
   106  			} else {
   107  				extracted = json.Null{}
   108  			}
   109  		default:
   110  			extracted = json.Null{}
   111  		}
   112  	case RowValueExpr:
   113  		switch data.(type) {
   114  		case json.Array:
   115  			rowValue := query.(RowValueExpr)
   116  			if rowValue.Child == nil {
   117  				extracted = data
   118  			} else {
   119  				ar := data.(json.Array)
   120  				elems := make(json.Array, 0, len(ar))
   121  				for _, v := range ar {
   122  					e, err := Extract(rowValue.Child, v)
   123  					if err != nil {
   124  						return extracted, err
   125  					}
   126  					elems = append(elems, e)
   127  				}
   128  				extracted = elems
   129  			}
   130  		default:
   131  			return extracted, errors.New("json value must be an array")
   132  		}
   133  	case TableExpr:
   134  		switch data.(type) {
   135  		case json.Object:
   136  			table := query.(TableExpr)
   137  			if table.Fields == nil {
   138  				extracted = json.Array{data}
   139  			} else {
   140  				obj := json.NewObject(len(table.Fields))
   141  				for _, field := range table.Fields {
   142  					e, err := Extract(field.Element, data)
   143  					if err != nil {
   144  						return extracted, err
   145  					}
   146  
   147  					obj.Add(field.FieldLabel(), e)
   148  				}
   149  				extracted = json.Array{obj}
   150  			}
   151  		case json.Array:
   152  			table := query.(TableExpr)
   153  			var fields []FieldExpr
   154  
   155  			if table.Fields != nil {
   156  				fields = table.Fields
   157  			}
   158  
   159  			array := data.(json.Array)
   160  			for _, v := range array {
   161  				obj, ok := v.(json.Object)
   162  				if !ok {
   163  					return extracted, errors.New("all elements in array must be objects")
   164  				}
   165  
   166  				if table.Fields == nil {
   167  					if fields == nil {
   168  						fields = make([]FieldExpr, 0, obj.Len())
   169  					}
   170  					for _, members := range obj.Members {
   171  						if !existsKeyInFields(members.Key, fields) {
   172  							fields = append(fields, FieldExpr{Element: Element{Label: members.Key}})
   173  						}
   174  					}
   175  				}
   176  			}
   177  
   178  			elems := make(json.Array, 0, len(array))
   179  			for _, v := range array {
   180  				obj := json.NewObject(len(fields))
   181  				for _, field := range fields {
   182  					e, err := Extract(field.Element, v)
   183  					if err != nil {
   184  						return extracted, err
   185  					}
   186  
   187  					obj.Add(field.FieldLabel(), e)
   188  				}
   189  				elems = append(elems, obj)
   190  			}
   191  			extracted = elems
   192  		default:
   193  			return extracted, errors.New("json value must be an array or object")
   194  		}
   195  	default:
   196  		return extracted, errors.New("invalid expression")
   197  	}
   198  
   199  	return extracted, err
   200  }
   201  
   202  func existsKeyInFields(key string, list []FieldExpr) bool {
   203  	for _, v := range list {
   204  		if key == v.Element.Label {
   205  			return true
   206  		}
   207  	}
   208  	return false
   209  }