Source file src/encoding/json/jsontext/example_test.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build goexperiment.jsonv2
     6  
     7  package jsontext_test
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"io"
    13  	"log"
    14  	"strings"
    15  
    16  	"encoding/json/jsontext"
    17  	"encoding/json/v2"
    18  )
    19  
    20  // This example demonstrates the use of the [Encoder] and [Decoder] to
    21  // parse and modify JSON without unmarshaling it into a concrete Go type.
    22  func Example_stringReplace() {
    23  	// Example input with non-idiomatic use of "Golang" instead of "Go".
    24  	const input = `{
    25  		"title": "Golang version 1 is released",
    26  		"author": "Andrew Gerrand",
    27  		"date": "2012-03-28",
    28  		"text": "Today marks a major milestone in the development of the Golang programming language.",
    29  		"otherArticles": [
    30  			"Twelve Years of Golang",
    31  			"The Laws of Reflection",
    32  			"Learn Golang from your browser"
    33  		]
    34  	}`
    35  
    36  	// Using a Decoder and Encoder, we can parse through every token,
    37  	// check and modify the token if necessary, and
    38  	// write the token to the output.
    39  	var replacements []jsontext.Pointer
    40  	in := strings.NewReader(input)
    41  	dec := jsontext.NewDecoder(in)
    42  	out := new(bytes.Buffer)
    43  	enc := jsontext.NewEncoder(out, jsontext.Multiline(true)) // expand for readability
    44  	for {
    45  		// Read a token from the input.
    46  		tok, err := dec.ReadToken()
    47  		if err != nil {
    48  			if err == io.EOF {
    49  				break
    50  			}
    51  			log.Fatal(err)
    52  		}
    53  
    54  		// Check whether the token contains the string "Golang" and
    55  		// replace each occurrence with "Go" instead.
    56  		if tok.Kind() == '"' && strings.Contains(tok.String(), "Golang") {
    57  			replacements = append(replacements, dec.StackPointer())
    58  			tok = jsontext.String(strings.ReplaceAll(tok.String(), "Golang", "Go"))
    59  		}
    60  
    61  		// Write the (possibly modified) token to the output.
    62  		if err := enc.WriteToken(tok); err != nil {
    63  			log.Fatal(err)
    64  		}
    65  	}
    66  
    67  	// Print the list of replacements and the adjusted JSON output.
    68  	if len(replacements) > 0 {
    69  		fmt.Println(`Replaced "Golang" with "Go" in:`)
    70  		for _, where := range replacements {
    71  			fmt.Println("\t" + where)
    72  		}
    73  		fmt.Println()
    74  	}
    75  	fmt.Println("Result:", out.String())
    76  
    77  	// Output:
    78  	// Replaced "Golang" with "Go" in:
    79  	// 	/title
    80  	// 	/text
    81  	// 	/otherArticles/0
    82  	// 	/otherArticles/2
    83  	//
    84  	// Result: {
    85  	// 	"title": "Go version 1 is released",
    86  	// 	"author": "Andrew Gerrand",
    87  	// 	"date": "2012-03-28",
    88  	// 	"text": "Today marks a major milestone in the development of the Go programming language.",
    89  	// 	"otherArticles": [
    90  	// 		"Twelve Years of Go",
    91  	// 		"The Laws of Reflection",
    92  	// 		"Learn Go from your browser"
    93  	// 	]
    94  	// }
    95  }
    96  
    97  // Directly embedding JSON within HTML requires special handling for safety.
    98  // Escape certain runes to prevent JSON directly treated as HTML
    99  // from being able to perform <script> injection.
   100  //
   101  // This example shows how to obtain equivalent behavior provided by the
   102  // v1 [encoding/json] package that is no longer directly supported by this package.
   103  // Newly written code that intermix JSON and HTML should instead be using the
   104  // [github.com/google/safehtml] module for safety purposes.
   105  func ExampleEscapeForHTML() {
   106  	page := struct {
   107  		Title string
   108  		Body  string
   109  	}{
   110  		Title: "Example Embedded Javascript",
   111  		Body:  `<script> console.log("Hello, world!"); </script>`,
   112  	}
   113  
   114  	b, err := json.Marshal(&page,
   115  		// Escape certain runes within a JSON string so that
   116  		// JSON will be safe to directly embed inside HTML.
   117  		jsontext.EscapeForHTML(true),
   118  		jsontext.EscapeForJS(true),
   119  		jsontext.Multiline(true)) // expand for readability
   120  	if err != nil {
   121  		log.Fatal(err)
   122  	}
   123  	fmt.Println(string(b))
   124  
   125  	// Output:
   126  	// {
   127  	// 	"Title": "Example Embedded Javascript",
   128  	// 	"Body": "\u003cscript\u003e console.log(\"Hello, world!\"); \u003c/script\u003e"
   129  	// }
   130  }
   131  

View as plain text