You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool/njson/json.go

89 lines
2.0 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package njson
import (
"bytes"
"encoding/json"
"fmt"
"io"
"strings"
)
// Marshal marshals v into json bytes.
// see json.Marshal
func Marshal(v any) ([]byte, error) {
return json.Marshal(v)
}
// MarshalStr marshals v into a string.
func MarshalStr(v any) (string, error) {
data, err := Marshal(v)
if err != nil {
return "", err
}
return string(data), nil
}
// MarshalSafe marshals v into json bytes.
// return an empty byte slice if an error occurred.
func MarshalSafe(v any) []byte {
ret, err := Marshal(v)
if err != nil {
return []byte{}
}
return ret
}
// MarshalStrSafe marshals v into a string.
// return an empty string if an error occurred.
func MarshalStrSafe(v any) string {
ret, err := MarshalStr(v)
if err != nil {
return ""
}
return ret
}
// Unmarshal data bytes into v.
func Unmarshal(data []byte, v any) error {
decoder := json.NewDecoder(bytes.NewReader(data))
if err := unmarshalUseNumber(decoder, v); err != nil {
return formatError(string(data), err)
}
return nil
}
// UnmarshalFromStr unmarshal v from str.
func UnmarshalFromStr(str string, v any) error {
decoder := json.NewDecoder(strings.NewReader(str))
if err := unmarshalUseNumber(decoder, v); err != nil {
return formatError(str, err)
}
return nil
}
// UnmarshalFromReader unmarshal v from reader.
func UnmarshalFromReader(reader io.Reader, v any) error {
var buf strings.Builder
teeReader := io.TeeReader(reader, &buf)
decoder := json.NewDecoder(teeReader)
if err := unmarshalUseNumber(decoder, v); err != nil {
return formatError(buf.String(), err)
}
return nil
}
// unmarshalUseNumber 避免出现科学计算如1e+100
// 这是由于默认 unmarshal 时会将大于6位的数值类型使用 float64 解析
// 同时也可以避免精度丢失 double -> float64 等
func unmarshalUseNumber(decoder *json.Decoder, v any) error {
decoder.UseNumber()
return decoder.Decode(v)
}
func formatError(v string, err error) error {
return fmt.Errorf("string: `%s`, error: `%w`", v, err)
}