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  }