| // Copyright 2023 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. | |
| //go:build goexperiment.jsonv2 | |
| package jsontext_test | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io" | |
| "log" | |
| "strings" | |
| "encoding/json/jsontext" | |
| "encoding/json/v2" | |
| ) | |
| // This example demonstrates the use of the [Encoder] and [Decoder] to | |
| // parse and modify JSON without unmarshaling it into a concrete Go type. | |
| func Example_stringReplace() { | |
| // Example input with non-idiomatic use of "Golang" instead of "Go". | |
| const input = `{ | |
| "title": "Golang version 1 is released", | |
| "author": "Andrew Gerrand", | |
| "date": "2012-03-28", | |
| "text": "Today marks a major milestone in the development of the Golang programming language.", | |
| "otherArticles": [ | |
| "Twelve Years of Golang", | |
| "The Laws of Reflection", | |
| "Learn Golang from your browser" | |
| ] | |
| }` | |
| // Using a Decoder and Encoder, we can parse through every token, | |
| // check and modify the token if necessary, and | |
| // write the token to the output. | |
| var replacements []jsontext.Pointer | |
| in := strings.NewReader(input) | |
| dec := jsontext.NewDecoder(in) | |
| out := new(bytes.Buffer) | |
| enc := jsontext.NewEncoder(out, jsontext.Multiline(true)) // expand for readability | |
| for { | |
| // Read a token from the input. | |
| tok, err := dec.ReadToken() | |
| if err != nil { | |
| if err == io.EOF { | |
| break | |
| } | |
| log.Fatal(err) | |
| } | |
| // Check whether the token contains the string "Golang" and | |
| // replace each occurrence with "Go" instead. | |
| if tok.Kind() == '"' && strings.Contains(tok.String(), "Golang") { | |
| replacements = append(replacements, dec.StackPointer()) | |
| tok = jsontext.String(strings.ReplaceAll(tok.String(), "Golang", "Go")) | |
| } | |
| // Write the (possibly modified) token to the output. | |
| if err := enc.WriteToken(tok); err != nil { | |
| log.Fatal(err) | |
| } | |
| } | |
| // Print the list of replacements and the adjusted JSON output. | |
| if len(replacements) > 0 { | |
| fmt.Println(`Replaced "Golang" with "Go" in:`) | |
| for _, where := range replacements { | |
| fmt.Println("\t" + where) | |
| } | |
| fmt.Println() | |
| } | |
| fmt.Println("Result:", out.String()) | |
| // Output: | |
| // Replaced "Golang" with "Go" in: | |
| // /title | |
| // /text | |
| // /otherArticles/0 | |
| // /otherArticles/2 | |
| // | |
| // Result: { | |
| // "title": "Go version 1 is released", | |
| // "author": "Andrew Gerrand", | |
| // "date": "2012-03-28", | |
| // "text": "Today marks a major milestone in the development of the Go programming language.", | |
| // "otherArticles": [ | |
| // "Twelve Years of Go", | |
| // "The Laws of Reflection", | |
| // "Learn Go from your browser" | |
| // ] | |
| // } | |
| } | |
| // Directly embedding JSON within HTML requires special handling for safety. | |
| // Escape certain runes to prevent JSON directly treated as HTML | |
| // from being able to perform <script> injection. | |
| // | |
| // This example shows how to obtain equivalent behavior provided by the | |
| // v1 [encoding/json] package that is no longer directly supported by this package. | |
| // Newly written code that intermix JSON and HTML should instead be using the | |
| // [github.com/google/safehtml] module for safety purposes. | |
| func ExampleEscapeForHTML() { | |
| page := struct { | |
| Title string | |
| Body string | |
| }{ | |
| Title: "Example Embedded Javascript", | |
| Body: `<script> console.log("Hello, world!"); </script>`, | |
| } | |
| b, err := json.Marshal(&page, | |
| // Escape certain runes within a JSON string so that | |
| // JSON will be safe to directly embed inside HTML. | |
| jsontext.EscapeForHTML(true), | |
| jsontext.EscapeForJS(true), | |
| jsontext.Multiline(true)) // expand for readability | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| fmt.Println(string(b)) | |
| // Output: | |
| // { | |
| // "Title": "Example Embedded Javascript", | |
| // "Body": "\u003cscript\u003e console.log(\"Hello, world!\"); \u003c/script\u003e" | |
| // } | |
| } | |