github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/json/badjson/typed.go (about) 1 package badjson 2 3 import ( 4 "bytes" 5 "strings" 6 7 E "github.com/sagernet/sing/common/exceptions" 8 "github.com/sagernet/sing/common/json" 9 "github.com/sagernet/sing/common/x/linkedhashmap" 10 ) 11 12 type TypedMap[K comparable, V any] struct { 13 linkedhashmap.Map[K, V] 14 } 15 16 func (m TypedMap[K, V]) MarshalJSON() ([]byte, error) { 17 buffer := new(bytes.Buffer) 18 buffer.WriteString("{") 19 items := m.Entries() 20 iLen := len(items) 21 for i, entry := range items { 22 keyContent, err := json.Marshal(entry.Key) 23 if err != nil { 24 return nil, err 25 } 26 buffer.WriteString(strings.TrimSpace(string(keyContent))) 27 buffer.WriteString(": ") 28 valueContent, err := json.Marshal(entry.Value) 29 if err != nil { 30 return nil, err 31 } 32 buffer.WriteString(strings.TrimSpace(string(valueContent))) 33 if i < iLen-1 { 34 buffer.WriteString(", ") 35 } 36 } 37 buffer.WriteString("}") 38 return buffer.Bytes(), nil 39 } 40 41 func (m *TypedMap[K, V]) UnmarshalJSON(content []byte) error { 42 decoder := json.NewDecoder(bytes.NewReader(content)) 43 m.Clear() 44 objectStart, err := decoder.Token() 45 if err != nil { 46 return err 47 } else if objectStart != json.Delim('{') { 48 return E.New("expected json object start, but starts with ", objectStart) 49 } 50 err = m.decodeJSON(decoder) 51 if err != nil { 52 return E.Cause(err, "decode json object content") 53 } 54 objectEnd, err := decoder.Token() 55 if err != nil { 56 return err 57 } else if objectEnd != json.Delim('}') { 58 return E.New("expected json object end, but ends with ", objectEnd) 59 } 60 return nil 61 } 62 63 func (m *TypedMap[K, V]) decodeJSON(decoder *json.Decoder) error { 64 for decoder.More() { 65 keyToken, err := decoder.Token() 66 if err != nil { 67 return err 68 } 69 keyContent, err := json.Marshal(keyToken) 70 if err != nil { 71 return err 72 } 73 var entryKey K 74 err = json.Unmarshal(keyContent, &entryKey) 75 if err != nil { 76 return err 77 } 78 var entryValue V 79 err = decoder.Decode(&entryValue) 80 if err != nil { 81 return err 82 } 83 m.Put(entryKey, entryValue) 84 } 85 return nil 86 }