cmd/flatten-approvals/main.go (87 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package main import ( "encoding/json" "flag" "fmt" "io" "log" "os" "path/filepath" ) var inplace = flag.Bool("i", false, "modify file in place") func main() { flag.Parse() if err := flatten(flag.Args()); err != nil { log.Fatal(err) } } func flatten(args []string) error { var filepaths []string for _, arg := range args { matches, err := filepath.Glob(arg) if err != nil { return err } filepaths = append(filepaths, matches...) } for _, filepath := range filepaths { if err := transform(filepath); err != nil { return fmt.Errorf("error transforming %q: %w", filepath, err) } } return nil } // transform []{"events": {"object": {"field": ...}}} to []{"field", "field", ...} func transform(filepath string) error { var input struct { Events []map[string]any `json:"events"` } if err := decodeJSONFile(filepath, &input); err != nil { return fmt.Errorf("could not read existing approved events file: %w", err) } out := make([]map[string][]any, 0, len(input.Events)) for _, event := range input.Events { fields := make(map[string][]any) flattenFields("", event, fields) out = append(out, fields) } var w io.Writer = os.Stdout if *inplace { f, err := os.Create(filepath) if err != nil { return err } defer f.Close() w = f } enc := json.NewEncoder(w) enc.SetIndent("", " ") return enc.Encode(out) } func flattenFields(k string, v any, out map[string][]any) { switch v := v.(type) { case map[string]any: for k2, v := range v { if k != "" { k2 = k + "." + k2 } flattenFields(k2, v, out) } case []any: for _, v := range v { flattenFields(k, v, out) } default: out[k] = append(out[k], v) } } func decodeJSONFile(path string, out interface{}) error { f, err := os.Open(path) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&out); err != nil { return fmt.Errorf("cannot unmarshal file %q: %w", path, err) } return nil }