github.com/mitranim/gg@v0.1.17/json.go (about)

     1  package gg
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  )
    10  
    11  // Uses `json.Marshal` to encode the given value as JSON, panicking on error.
    12  func JsonBytes[A any](val A) []byte {
    13  	return Try1(JsonBytesCatch(val))
    14  }
    15  
    16  /*
    17  Uses `json.MarshalIndent` to encode the given value as JSON with indentation
    18  controlled by the `Indent` variable, panicking on error.
    19  */
    20  func JsonBytesIndent[A any](val A) []byte {
    21  	return Try1(JsonBytesIndentCatch(val))
    22  }
    23  
    24  /*
    25  Same as `json.Marshal` but sometimes marginally more efficient. Avoids spurious
    26  heap escape of the input.
    27  */
    28  func JsonBytesCatch[A any](val A) ([]byte, error) {
    29  	return json.Marshal(AnyNoEscUnsafe(val))
    30  }
    31  
    32  /*
    33  Same as `json.MarshalIndent`, but uses the default indentation controlled by the
    34  `Indent` variable. Also sometimes marginally more efficient. Avoids spurious
    35  heap escape of the input.
    36  */
    37  func JsonBytesIndentCatch[A any](val A) ([]byte, error) {
    38  	return json.MarshalIndent(AnyNoEscUnsafe(val), ``, Indent)
    39  }
    40  
    41  // Encodes the input as a JSON string, panicking on error.
    42  func JsonString[A any](val A) string { return ToString(JsonBytes(val)) }
    43  
    44  /*
    45  Encodes the input as a JSON string, using default indentation controlled by the
    46  `Indent` variable.
    47  */
    48  func JsonStringIndent[A any](val A) string { return ToString(JsonBytesIndent(val)) }
    49  
    50  /*
    51  Shortcut for implementing JSON encoding of `Nullable` types.
    52  Mostly for internal use.
    53  */
    54  func JsonBytesNullCatch[A any, B NullableValGetter[A]](val B) ([]byte, error) {
    55  	if val.IsNull() {
    56  		return ToBytes(`null`), nil
    57  	}
    58  	return JsonBytesCatch(val.Get())
    59  }
    60  
    61  /*
    62  Shortcut for parsing the given string or byte slice into a value of the given
    63  type. Panics on errors.
    64  */
    65  func JsonParseTo[Out any, Src Text](src Src) (out Out) {
    66  	JsonParse(src, &out)
    67  	return
    68  }
    69  
    70  /*
    71  Shortcut for parsing the given string or byte slice into a pointer of the given
    72  type. Panics on errors.
    73  */
    74  func JsonParse[Out any, Src Text](src Src, out *Out) {
    75  	Try(JsonParseCatch(src, out))
    76  }
    77  
    78  /*
    79  Parses the given string or byte slice into a pointer of the given type. Similar
    80  to `json.Unmarshal`, but avoids the overhead of byte-string conversion and
    81  spurious escapes.
    82  */
    83  func JsonParseCatch[Out any, Src Text](src Src, out *Out) error {
    84  	if out != nil {
    85  		return json.Unmarshal(ToBytes(src), AnyNoEscUnsafe(out))
    86  	}
    87  	return nil
    88  }
    89  
    90  /*
    91  Shortcut for decoding the content of the given file into a value of the given
    92  type. Panics on error.
    93  */
    94  func JsonDecodeFileTo[A any](path string) (out A) {
    95  	JsonDecodeFile(path, &out)
    96  	return
    97  }
    98  
    99  /*
   100  Shortcut for decoding the content of the given file into a pointer of the given
   101  type. Panics on error.
   102  */
   103  func JsonDecodeFile[A any](path string, out *A) {
   104  	if out != nil {
   105  		JsonDecodeClose(Try1(os.Open(path)), NoEscUnsafe(out))
   106  	}
   107  }
   108  
   109  /*
   110  Shortcut for writing the JSON encoding of the given value to a file at the given
   111  path. Intermediary directories are created automatically. Any existing file is
   112  truncated.
   113  */
   114  func JsonEncodeFile[A any](path string, src A) {
   115  	MkdirAll(filepath.Dir(path))
   116  
   117  	file := Try1(os.Create(path))
   118  	defer file.Close()
   119  
   120  	Try(json.NewEncoder(file).Encode(src))
   121  	Try(file.Close())
   122  }
   123  
   124  /*
   125  Uses `json.Decoder` to decode one JSON entry/line from the reader, writing to
   126  the given output. Always closes the reader. Panics on errors.
   127  */
   128  func JsonDecodeClose[A any](src io.ReadCloser, out *A) {
   129  	defer Close(src)
   130  	if out != nil {
   131  		Try(json.NewDecoder(NoEscUnsafe(src)).Decode(AnyNoEscUnsafe(out)))
   132  	}
   133  }
   134  
   135  // True if the input is "null" or blank. Ignores whitespace.
   136  func IsJsonEmpty[A Text](val A) bool {
   137  	src := strings.TrimSpace(ToString(val))
   138  	return src == `` || src == `null`
   139  }