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 }