json.go 1.42 KB
Newer Older
1
package jsonutil
protolambda's avatar
protolambda committed
2 3 4

import (
	"encoding/json"
5
	"errors"
protolambda's avatar
protolambda committed
6 7
	"fmt"
	"io"
8 9

	"github.com/ethereum-optimism/optimism/op-service/ioutil"
protolambda's avatar
protolambda committed
10 11
)

12
func LoadJSON[X any](inputPath string) (*X, error) {
13 14 15
	if inputPath == "" {
		return nil, errors.New("no path specified")
	}
16
	var f io.ReadCloser
17
	f, err := ioutil.OpenDecompressed(inputPath)
protolambda's avatar
protolambda committed
18 19 20 21 22
	if err != nil {
		return nil, fmt.Errorf("failed to open file %q: %w", inputPath, err)
	}
	defer f.Close()
	var state X
23 24
	decoder := json.NewDecoder(f)
	if err := decoder.Decode(&state); err != nil {
protolambda's avatar
protolambda committed
25 26
		return nil, fmt.Errorf("failed to decode file %q: %w", inputPath, err)
	}
27 28 29 30
	// We are only expecting 1 JSON object - confirm there is no trailing data
	if _, err := decoder.Token(); err != io.EOF {
		return nil, fmt.Errorf("unexpected trailing data in file %q", inputPath)
	}
protolambda's avatar
protolambda committed
31 32 33
	return &state, nil
}

34 35 36 37
func WriteJSON[X any](value X, target ioutil.OutputTarget) error {
	out, closer, abort, err := target()
	if err != nil {
		return err
38
	}
39 40
	if out == nil {
		return nil // No output stream selected so skip generating the content entirely
protolambda's avatar
protolambda committed
41
	}
42
	defer abort()
protolambda's avatar
protolambda committed
43
	enc := json.NewEncoder(out)
44
	enc.SetIndent("", "  ")
protolambda's avatar
protolambda committed
45 46 47
	if err := enc.Encode(value); err != nil {
		return fmt.Errorf("failed to encode to JSON: %w", err)
	}
48
	_, err = out.Write([]byte{'\n'})
protolambda's avatar
protolambda committed
49 50 51
	if err != nil {
		return fmt.Errorf("failed to append new-line: %w", err)
	}
52
	if err := closer.Close(); err != nil {
53 54
		return fmt.Errorf("failed to finish write: %w", err)
	}
protolambda's avatar
protolambda committed
55 56
	return nil
}