github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/badjson/object.go (about) 1 package badjson 2 3 import ( 4 "bytes" 5 "strings" 6 7 "github.com/inazumav/sing-box/common/json" 8 E "github.com/sagernet/sing/common/exceptions" 9 "github.com/sagernet/sing/common/x/linkedhashmap" 10 ) 11 12 type JSONObject struct { 13 linkedhashmap.Map[string, any] 14 } 15 16 func (m JSONObject) 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 *JSONObject) 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 *JSONObject) decodeJSON(decoder *json.Decoder) error { 64 for decoder.More() { 65 var entryKey string 66 keyToken, err := decoder.Token() 67 if err != nil { 68 return err 69 } 70 entryKey = keyToken.(string) 71 var entryValue any 72 entryValue, err = decodeJSON(decoder) 73 if err != nil { 74 return E.Cause(err, "decode value for ", entryKey) 75 } 76 m.Put(entryKey, entryValue) 77 } 78 return nil 79 }