// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package jsonimport// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029// so that the JSON will be safe to embed inside HTML <script> tags.// For historical reasons, web browsers don't honor standard HTML// escaping within <script> tags, so an alternative JSON encoding must be used.func ( *bytes.Buffer, []byte) { .Grow(len()) .Write(appendHTMLEscape(.AvailableBuffer(), ))}func appendHTMLEscape(, []byte) []byte {// The characters can only appear in string literals, // so just scan the string one byte at a time. := 0for , := range {if == '<' || == '>' || == '&' { = append(, [:]...) = append(, '\\', 'u', '0', '0', hex[>>4], hex[&0xF]) = + 1 }// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).if == 0xE2 && +2 < len() && [+1] == 0x80 && [+2]&^1 == 0xA8 { = append(, [:]...) = append(, '\\', 'u', '2', '0', '2', hex[[+2]&0xF]) = + len("\u2029") } }returnappend(, [:]...)}// Compact appends to dst the JSON-encoded src with// insignificant space characters elided.func ( *bytes.Buffer, []byte) error { .Grow(len()) := .AvailableBuffer() , := appendCompact(, , false) .Write()return}func appendCompact(, []byte, bool) ([]byte, error) { := len() := newScanner()deferfreeScanner() := 0for , := range {if && ( == '<' || == '>' || == '&') {if < { = append(, [:]...) } = append(, '\\', 'u', '0', '0', hex[>>4], hex[&0xF]) = + 1 }// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).if && == 0xE2 && +2 < len() && [+1] == 0x80 && [+2]&^1 == 0xA8 {if < { = append(, [:]...) } = append(, '\\', 'u', '2', '0', '2', hex[[+2]&0xF]) = + 3 } := .step(, )if >= scanSkipSpace {if == scanError {break }if < { = append(, [:]...) } = + 1 } }if .eof() == scanError {return [:], .err }if < len() { = append(, [:]...) }return , nil}func appendNewline( []byte, , string, int) []byte { = append(, '\n') = append(, ...)for := 0; < ; ++ { = append(, ...) }return}// indentGrowthFactor specifies the growth factor of indenting JSON input.// Empirically, the growth factor was measured to be between 1.4x to 1.8x// for some set of compacted JSON with the indent being a single tab.// Specify a growth factor slightly larger than what is observed// to reduce probability of allocation in appendIndent.// A factor no higher than 2 ensures that wasted space never exceeds 50%.const indentGrowthFactor = 2// Indent appends to dst an indented form of the JSON-encoded src.// Each element in a JSON object or array begins on a new,// indented line beginning with prefix followed by one or more// copies of indent according to the indentation nesting.// The data appended to dst does not begin with the prefix nor// any indentation, to make it easier to embed inside other formatted JSON data.// Although leading space characters (space, tab, carriage return, newline)// at the beginning of src are dropped, trailing space characters// at the end of src are preserved and copied to dst.// For example, if src has no trailing spaces, neither will dst;// if src ends in a trailing newline, so will dst.func ( *bytes.Buffer, []byte, , string) error { .Grow(indentGrowthFactor * len()) := .AvailableBuffer() , := appendIndent(, , , ) .Write()return}func appendIndent(, []byte, , string) ([]byte, error) { := len() := newScanner()deferfreeScanner() := false := 0for , := range { .bytes++ := .step(, )if == scanSkipSpace {continue }if == scanError {break }if && != scanEndObject && != scanEndArray { = false ++ = appendNewline(, , , ) }// Emit semantically uninteresting bytes // (in particular, punctuation in strings) unmodified.if == scanContinue { = append(, )continue }// Add spacing around real punctuation.switch {case'{', '[':// delay indent so that empty object and array are formatted as {} and []. = true = append(, )case',': = append(, ) = appendNewline(, , , )case':': = append(, , ' ')case'}', ']':if {// suppress indent in empty object/array = false } else { -- = appendNewline(, , , ) } = append(, )default: = append(, ) } }if .eof() == scanError {return [:], .err }return , nil}
The pages are generated with Goldsv0.6.9-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.