gitee.com/h79/goutils@v1.22.10/common/json/json.go (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"gitee.com/h79/goutils/common/file"
     7  	"gitee.com/h79/goutils/common/result"
     8  	"os"
     9  	"strings"
    10  	"unicode"
    11  	"unicode/utf16"
    12  	"unicode/utf8"
    13  )
    14  
    15  type DumpOption func(enc *json.Encoder)
    16  
    17  func EscapeHTML(escape bool) DumpOption {
    18  	return func(enc *json.Encoder) {
    19  		enc.SetEscapeHTML(escape)
    20  	}
    21  }
    22  
    23  // Indent sets the indentation level (passed as string of spaces) for DumpBytes/DumpString
    24  func Indent(prefix, indent string) DumpOption {
    25  	return func(enc *json.Encoder) {
    26  		enc.SetIndent(prefix, indent)
    27  	}
    28  }
    29  
    30  // DumpBytes convert Go data object to JSON []byte
    31  func DumpBytes(obj interface{}, options ...DumpOption) ([]byte, error) {
    32  	var b bytes.Buffer
    33  	enc := json.NewEncoder(&b)
    34  	enc.SetEscapeHTML(false)
    35  
    36  	for _, opt := range options {
    37  		opt(enc)
    38  	}
    39  	err := enc.Encode(obj)
    40  	return b.Bytes(), err
    41  }
    42  
    43  // DumpString encode Go data object to JSON string
    44  func DumpString(obj interface{}, options ...DumpOption) (string, error) {
    45  	if res, err := DumpBytes(obj, options...); err != nil {
    46  		return "", err
    47  	} else {
    48  		return string(res), nil
    49  	}
    50  }
    51  
    52  // MustDumpBytes encode Go data object to JSON []byte (panic in case of error)
    53  func MustDumpBytes(obj interface{}, options ...DumpOption) []byte {
    54  	if res, err := DumpBytes(obj, options...); err != nil {
    55  		panic(err)
    56  	} else {
    57  		return res
    58  	}
    59  }
    60  
    61  // MustDumpString encode Go data object to JSON string (panic in case of error)
    62  func MustDumpString(obj interface{}, options ...DumpOption) string {
    63  	if res, err := DumpString(obj, options...); err != nil {
    64  		panic(err)
    65  	} else {
    66  		return res
    67  	}
    68  }
    69  
    70  // ToString 序列化参数
    71  func ToString(o interface{}) string {
    72  	// 序列化一次
    73  	raw, _ := json.Marshal(o)
    74  
    75  	// 反序列化为map
    76  	m := make(map[string]interface{})
    77  	reader := bytes.NewReader(raw)
    78  	decode := json.NewDecoder(reader)
    79  	decode.UseNumber()
    80  	_ = decode.Decode(&m)
    81  
    82  	// 重新做一次序列化,并禁用Html Escape
    83  	buffer := bytes.NewBufferString("")
    84  	encoder := json.NewEncoder(buffer)
    85  	encoder.SetEscapeHTML(false)
    86  	_ = encoder.Encode(m)
    87  
    88  	// Trim掉末尾的换行符
    89  	return strings.TrimSpace(buffer.String())
    90  }
    91  
    92  func Write(name string, data interface{}, perm os.FileMode) error {
    93  	return file.WriteFileName(name, perm, func(w *os.File) error {
    94  		enc := json.NewEncoder(w)
    95  		if err := enc.Encode(data); err != nil {
    96  			return result.Errorf(result.ErrJson, "Encode %s json failed,err: %v", name, err).Log()
    97  		}
    98  		return nil
    99  	})
   100  }
   101  
   102  func Read(name string, data interface{}) error {
   103  	_, err := file.ReadFileName(name, func(r *os.File) error {
   104  		dec := json.NewDecoder(r)
   105  		if err := dec.Decode(data); err != nil {
   106  			return result.Errorf(result.ErrJson, "Decode %s json failed,err: %v", name, err).Log()
   107  		}
   108  		return nil
   109  	})
   110  	return err
   111  }
   112  
   113  func UnQuoteBytes(s []byte) (t []byte, ok bool) {
   114  	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
   115  		return s, true
   116  	}
   117  	s = s[1 : len(s)-1]
   118  
   119  	// Check for unusual characters. If there are none,
   120  	// then no unquoting is needed, so return a slice of the
   121  	// original bytes.
   122  	r := 0
   123  	for r < len(s) {
   124  		c := s[r]
   125  		if c == '\\' || c == '"' || c < ' ' {
   126  			break
   127  		}
   128  		if c < utf8.RuneSelf {
   129  			r++
   130  			continue
   131  		}
   132  		rr, size := utf8.DecodeRune(s[r:])
   133  		if rr == utf8.RuneError && size == 1 {
   134  			break
   135  		}
   136  		r += size
   137  	}
   138  	if r == len(s) {
   139  		return s, true
   140  	}
   141  
   142  	b := make([]byte, len(s)+2*utf8.UTFMax)
   143  	w := copy(b, s[0:r])
   144  	for r < len(s) {
   145  		// Out of room? Can only happen if s is full of
   146  		// malformed UTF-8 and we're replacing each
   147  		// byte with RuneError.
   148  		if w >= len(b)-2*utf8.UTFMax {
   149  			nb := make([]byte, (len(b)+utf8.UTFMax)*2)
   150  			copy(nb, b[0:w])
   151  			b = nb
   152  		}
   153  		switch c := s[r]; {
   154  		case c == '\\':
   155  			r++
   156  			if r >= len(s) {
   157  				return
   158  			}
   159  			switch s[r] {
   160  			default:
   161  				return
   162  			case '"', '\\', '/', '\'':
   163  				b[w] = s[r]
   164  				r++
   165  				w++
   166  			case 'b':
   167  				b[w] = '\b'
   168  				r++
   169  				w++
   170  			case 'f':
   171  				b[w] = '\f'
   172  				r++
   173  				w++
   174  			case 'n':
   175  				b[w] = '\n'
   176  				r++
   177  				w++
   178  			case 'r':
   179  				b[w] = '\r'
   180  				r++
   181  				w++
   182  			case 't':
   183  				b[w] = '\t'
   184  				r++
   185  				w++
   186  			case 'u':
   187  				r--
   188  				rr := getU4(s[r:])
   189  				if rr < 0 {
   190  					return
   191  				}
   192  				r += 6
   193  				if utf16.IsSurrogate(rr) {
   194  					rr1 := getU4(s[r:])
   195  					if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
   196  						// A valid pair; consume.
   197  						r += 6
   198  						w += utf8.EncodeRune(b[w:], dec)
   199  						break
   200  					}
   201  					// Invalid surrogate; fall back to replacement rune.
   202  					rr = unicode.ReplacementChar
   203  				}
   204  				w += utf8.EncodeRune(b[w:], rr)
   205  			}
   206  
   207  		// Quote, control characters are invalid.
   208  		case c == '"', c < ' ':
   209  			return
   210  
   211  		// ASCII
   212  		case c < utf8.RuneSelf:
   213  			b[w] = c
   214  			r++
   215  			w++
   216  
   217  		// Coerce to well-formed UTF-8.
   218  		default:
   219  			rr, size := utf8.DecodeRune(s[r:])
   220  			r += size
   221  			w += utf8.EncodeRune(b[w:], rr)
   222  		}
   223  	}
   224  	return b[0:w], true
   225  }
   226  
   227  // getU4 decodes \uXXXX from the beginning of s, returning the hex value,
   228  // or it returns -1.
   229  func getU4(s []byte) rune {
   230  	if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
   231  		return -1
   232  	}
   233  	var r rune
   234  	for _, c := range s[2:6] {
   235  		switch {
   236  		case '0' <= c && c <= '9':
   237  			c = c - '0'
   238  		case 'a' <= c && c <= 'f':
   239  			c = c - 'a' + 10
   240  		case 'A' <= c && c <= 'F':
   241  			c = c - 'A' + 10
   242  		default:
   243  			return -1
   244  		}
   245  		r = r*16 + rune(c)
   246  	}
   247  	return r
   248  }
   249  
   250  type coder struct {
   251  }
   252  
   253  func (j *coder) Unmarshal(content []byte, v interface{}) error {
   254  	return json.Unmarshal(content, v)
   255  }
   256  
   257  func (j *coder) Marshal(v interface{}) ([]byte, error) {
   258  	return json.Marshal(v)
   259  }
   260  
   261  var DefaultCoder = &coder{}