github.com/galdor/go-ejson@v0.0.0-20231201100034-d335379f26b0/json.go (about)

     1  package ejson
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"strings"
     9  )
    10  
    11  // It would be nice to have a DecodeStrict() function which would use
    12  // (*json.Decoder).DisallowUnknownFields(). Infortunately, the errors produced
    13  // this way are not structured and therefore unusable. There is no way out
    14  // this whole mess without rewriting an unmarshaller based on
    15  // (*json.Decoder).Token(). This would increase memory pressure, but this is
    16  // irrelevant for most use cases and would allow much better error reporting.
    17  
    18  func Unmarshal(data []byte, dest interface{}) error {
    19  	d := json.NewDecoder(bytes.NewReader(data))
    20  	return UnmarshalDecoder(d, dest)
    21  }
    22  
    23  func UnmarshalDecoder(d *json.Decoder, dest interface{}) error {
    24  	if err := d.Decode(dest); err != nil {
    25  		return ConvertUnmarshallingError(err)
    26  	}
    27  
    28  	return Validate(dest)
    29  
    30  }
    31  
    32  func UnmarshalReader(r io.Reader, dest interface{}) error {
    33  	d := json.NewDecoder(r)
    34  	return UnmarshalDecoder(d, dest)
    35  }
    36  
    37  func ConvertUnmarshallingError(err error) error {
    38  	switch err2 := err.(type) {
    39  	case *json.UnmarshalTypeError:
    40  		var pointer Pointer
    41  
    42  		if err2.Field != "" {
    43  			parts := strings.Split(err2.Field, ".")
    44  
    45  			// The Go type system is still completely broken
    46  			parts2 := make([]interface{}, len(parts))
    47  			for i, p := range parts {
    48  				parts2[i] = p
    49  			}
    50  
    51  			pointer = NewPointer(parts2...)
    52  		}
    53  
    54  		message := fmt.Sprintf("cannot decode %v into value of type %v",
    55  			err2.Value, err2.Type)
    56  
    57  		return ValidationErrors{
    58  			&ValidationError{
    59  				Pointer: pointer,
    60  				Code:    "invalid_value_type",
    61  				Message: message,
    62  			},
    63  		}
    64  
    65  	default:
    66  		return err
    67  	}
    68  }