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