github.com/lestrrat-go/jwx/v2@v2.0.21/internal/json/json.go (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"sync"
     8  
     9  	"github.com/lestrrat-go/jwx/v2/internal/base64"
    10  )
    11  
    12  var muGlobalConfig sync.RWMutex
    13  var useNumber bool
    14  
    15  // Sets the global configuration for json decoding
    16  func DecoderSettings(inUseNumber bool) {
    17  	muGlobalConfig.Lock()
    18  	useNumber = inUseNumber
    19  	muGlobalConfig.Unlock()
    20  }
    21  
    22  // Unmarshal respects the values specified in DecoderSettings,
    23  // and uses a Decoder that has certain features turned on/off
    24  func Unmarshal(b []byte, v interface{}) error {
    25  	dec := NewDecoder(bytes.NewReader(b))
    26  	return dec.Decode(v)
    27  }
    28  
    29  func AssignNextBytesToken(dst *[]byte, dec *Decoder) error {
    30  	var val string
    31  	if err := dec.Decode(&val); err != nil {
    32  		return fmt.Errorf(`error reading next value: %w`, err)
    33  	}
    34  
    35  	buf, err := base64.DecodeString(val)
    36  	if err != nil {
    37  		return fmt.Errorf(`expected base64 encoded []byte (%T)`, val)
    38  	}
    39  	*dst = buf
    40  	return nil
    41  }
    42  
    43  func ReadNextStringToken(dec *Decoder) (string, error) {
    44  	var val string
    45  	if err := dec.Decode(&val); err != nil {
    46  		return "", fmt.Errorf(`error reading next value: %w`, err)
    47  	}
    48  	return val, nil
    49  }
    50  
    51  func AssignNextStringToken(dst **string, dec *Decoder) error {
    52  	val, err := ReadNextStringToken(dec)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	*dst = &val
    57  	return nil
    58  }
    59  
    60  // FlattenAudience is a flag to specify if we should flatten the "aud"
    61  // entry to a string when there's only one entry.
    62  // In jwx < 1.1.8 we just dumped everything as an array of strings,
    63  // but apparently AWS Cognito doesn't handle this well.
    64  //
    65  // So now we have the ability to dump "aud" as a string if there's
    66  // only one entry, but we need to retain the old behavior so that
    67  // we don't accidentally break somebody else's code. (e.g. messing
    68  // up how signatures are calculated)
    69  var FlattenAudience uint32
    70  
    71  func EncodeAudience(enc *Encoder, aud []string, flatten bool) error {
    72  	var val interface{}
    73  	if len(aud) == 1 && flatten {
    74  		val = aud[0]
    75  	} else {
    76  		val = aud
    77  	}
    78  	return enc.Encode(val)
    79  }
    80  
    81  // DecodeCtx is an interface for objects that needs that extra something
    82  // when decoding JSON into an object.
    83  type DecodeCtx interface {
    84  	Registry() *Registry
    85  }
    86  
    87  // DecodeCtxContainer is used to differentiate objects that can carry extra
    88  // decoding hints and those who can't.
    89  type DecodeCtxContainer interface {
    90  	DecodeCtx() DecodeCtx
    91  	SetDecodeCtx(DecodeCtx)
    92  }
    93  
    94  // stock decodeCtx. should cover 80% of the cases
    95  type decodeCtx struct {
    96  	registry *Registry
    97  }
    98  
    99  func NewDecodeCtx(r *Registry) DecodeCtx {
   100  	return &decodeCtx{registry: r}
   101  }
   102  
   103  func (dc *decodeCtx) Registry() *Registry {
   104  	return dc.registry
   105  }
   106  
   107  func Dump(v interface{}) {
   108  	enc := NewEncoder(os.Stdout)
   109  	enc.SetIndent("", "  ")
   110  	//nolint:errchkjson
   111  	_ = enc.Encode(v)
   112  }