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) }