stringJsonMarshal is replacement for json.Marshal() function only for string type. This function is encodeState.string(string, escapeHTML) in "encoding/json/encode.go". It should be in sync with encodeState.string function.
(s string)
| 562 | // This function is encodeState.string(string, escapeHTML) in "encoding/json/encode.go". |
| 563 | // It should be in sync with encodeState.string function. |
| 564 | func stringJsonMarshal(s string) []byte { |
| 565 | e := bufferPool.Get().(*bytes.Buffer) |
| 566 | e.Reset() |
| 567 | |
| 568 | e.WriteByte('"') |
| 569 | start := 0 |
| 570 | for i := 0; i < len(s); { |
| 571 | if b := s[i]; b < utf8.RuneSelf { |
| 572 | if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { |
| 573 | i++ |
| 574 | continue |
| 575 | } |
| 576 | if start < i { |
| 577 | e.WriteString(s[start:i]) |
| 578 | } |
| 579 | e.WriteByte('\\') |
| 580 | switch b { |
| 581 | case '\\', '"': |
| 582 | e.WriteByte(b) |
| 583 | case '\n': |
| 584 | e.WriteByte('n') |
| 585 | case '\r': |
| 586 | e.WriteByte('r') |
| 587 | case '\t': |
| 588 | e.WriteByte('t') |
| 589 | default: |
| 590 | // This encodes bytes < 0x20 except for \t, \n and \r. |
| 591 | // If escapeHTML is set, it also escapes <, >, and & |
| 592 | // because they can lead to security holes when |
| 593 | // user-controlled strings are rendered into JSON |
| 594 | // and served to some browsers. |
| 595 | e.WriteString(`u00`) |
| 596 | e.WriteByte(hex[b>>4]) |
| 597 | e.WriteByte(hex[b&0xF]) |
| 598 | } |
| 599 | i++ |
| 600 | start = i |
| 601 | continue |
| 602 | } |
| 603 | c, size := utf8.DecodeRuneInString(s[i:]) |
| 604 | if c == utf8.RuneError && size == 1 { |
| 605 | if start < i { |
| 606 | e.WriteString(s[start:i]) |
| 607 | } |
| 608 | e.WriteString(`\ufffd`) |
| 609 | i += size |
| 610 | start = i |
| 611 | continue |
| 612 | } |
| 613 | // U+2028 is LINE SEPARATOR. |
| 614 | // U+2029 is PARAGRAPH SEPARATOR. |
| 615 | // They are both technically valid characters in JSON strings, |
| 616 | // but don't work in JSONP, which has to be evaluated as JavaScript, |
| 617 | // and can lead to security holes there. It is valid JSON to |
| 618 | // escape them, so we do so unconditionally. |
| 619 | // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. |
| 620 | if c == '\u2028' || c == '\u2029' { |
| 621 | if start < i { |