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