package badjson import ( "bytes" "strings" "github.com/sagernet/sing-box/common/json" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/x/linkedhashmap" ) type JSONObject struct { linkedhashmap.Map[string, any] } func (m *JSONObject) MarshalJSON() ([]byte, error) { buffer := new(bytes.Buffer) buffer.WriteString("{") items := m.Entries() iLen := len(items) for i, entry := range items { keyContent, err := json.Marshal(entry.Key) if err != nil { return nil, err } buffer.WriteString(strings.TrimSpace(string(keyContent))) buffer.WriteString(": ") valueContent, err := json.Marshal(entry.Value) if err != nil { return nil, err } buffer.WriteString(strings.TrimSpace(string(valueContent))) if i < iLen-1 { buffer.WriteString(", ") } } buffer.WriteString("}") return buffer.Bytes(), nil } func (m *JSONObject) UnmarshalJSON(content []byte) error { decoder := json.NewDecoder(bytes.NewReader(content)) m.Clear() objectStart, err := decoder.Token() if err != nil { return err } else if objectStart != json.Delim('{') { return E.New("expected json object start, but starts with ", objectStart) } err = m.decodeJSON(decoder) if err != nil { return E.Cause(err, "decode json object content") } objectEnd, err := decoder.Token() if err != nil { return err } else if objectEnd != json.Delim('}') { return E.New("expected json object end, but ends with ", objectEnd) } return nil } func (m *JSONObject) decodeJSON(decoder *json.Decoder) error { for decoder.More() { var entryKey string keyToken, err := decoder.Token() if err != nil { return err } entryKey = keyToken.(string) var entryValue any entryValue, err = decodeJSON(decoder) if err != nil { return E.Cause(err, "decode value for ", entryKey) } m.Put(entryKey, entryValue) } return nil }