pkg.re/essentialkaos/ek.10@v12.41.0+incompatible/jsonutil/jsonutil.go (about)

     1  // Package jsonutil provides methods for working with JSON data
     2  package jsonutil
     3  
     4  // ////////////////////////////////////////////////////////////////////////////////// //
     5  //                                                                                    //
     6  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
     7  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     8  //                                                                                    //
     9  // ////////////////////////////////////////////////////////////////////////////////// //
    10  
    11  import (
    12  	"bufio"
    13  	"compress/gzip"
    14  	"encoding/json"
    15  	"io"
    16  	"os"
    17  )
    18  
    19  // ////////////////////////////////////////////////////////////////////////////////// //
    20  
    21  // GzipLevel is default Gzip compression level
    22  var GzipLevel = gzip.BestSpeed
    23  
    24  // ////////////////////////////////////////////////////////////////////////////////// //
    25  
    26  // Read reads and decode JSON file
    27  func Read(file string, v interface{}) error {
    28  	return readFile(file, v, false)
    29  }
    30  
    31  // ReadGz reads and decode gzipped JSON file
    32  func ReadGz(file string, v interface{}) error {
    33  	return readFile(file, v, true)
    34  }
    35  
    36  // Write encodes data to JSON and save it to file
    37  func Write(file string, v interface{}, perms ...os.FileMode) error {
    38  	return writeFile(file, v, perms, false)
    39  }
    40  
    41  // Write encodes data to gzipped JSON and save it to file
    42  func WriteGz(file string, v interface{}, perms ...os.FileMode) error {
    43  	return writeFile(file, v, perms, true)
    44  }
    45  
    46  // ////////////////////////////////////////////////////////////////////////////////// //
    47  
    48  func readFile(file string, v interface{}, compress bool) error {
    49  	fd, err := os.Open(file)
    50  
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	defer fd.Close()
    56  
    57  	return readData(fd, v, compress)
    58  }
    59  
    60  func readData(rw io.ReadWriter, v interface{}, compress bool) error {
    61  	var err error
    62  	var dr io.Reader
    63  
    64  	r := bufio.NewReader(rw)
    65  
    66  	if compress {
    67  		dr, err = gzip.NewReader(r)
    68  
    69  		if err != nil {
    70  			return err
    71  		}
    72  	} else {
    73  		dr = r
    74  	}
    75  
    76  	return json.NewDecoder(dr).Decode(v)
    77  }
    78  
    79  func writeFile(file string, v interface{}, perms []os.FileMode, compressed bool) error {
    80  	var perm os.FileMode = 0644
    81  
    82  	if len(perms) != 0 {
    83  		perm = perms[0]
    84  	}
    85  
    86  	fd, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
    87  
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	defer fd.Close()
    93  
    94  	return writeData(fd, v, compressed)
    95  }
    96  
    97  func writeData(rw io.ReadWriter, v interface{}, compressed bool) error {
    98  	var err error
    99  	var je *json.Encoder
   100  	var gw *gzip.Writer
   101  
   102  	w := bufio.NewWriter(rw)
   103  
   104  	if compressed {
   105  		gw, err = gzip.NewWriterLevel(w, GzipLevel)
   106  
   107  		if err != nil {
   108  			return err
   109  		}
   110  
   111  		je = json.NewEncoder(gw)
   112  	} else {
   113  		je = json.NewEncoder(w)
   114  	}
   115  
   116  	je.SetIndent("", "  ")
   117  
   118  	err = je.Encode(v)
   119  
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	if compressed {
   125  		err = gw.Close()
   126  
   127  		if err != nil {
   128  			return err
   129  		}
   130  	}
   131  
   132  	return w.Flush()
   133  }