...

Source file src/github.com/gin-gonic/gin/render/json.go

Documentation: github.com/gin-gonic/gin/render

     1  // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package render
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"html/template"
    11  	"net/http"
    12  
    13  	"github.com/gin-gonic/gin/internal/bytesconv"
    14  	"github.com/gin-gonic/gin/internal/json"
    15  )
    16  
    17  // JSON contains the given interface object.
    18  type JSON struct {
    19  	Data any
    20  }
    21  
    22  // IndentedJSON contains the given interface object.
    23  type IndentedJSON struct {
    24  	Data any
    25  }
    26  
    27  // SecureJSON contains the given interface object and its prefix.
    28  type SecureJSON struct {
    29  	Prefix string
    30  	Data   any
    31  }
    32  
    33  // JsonpJSON contains the given interface object its callback.
    34  type JsonpJSON struct {
    35  	Callback string
    36  	Data     any
    37  }
    38  
    39  // AsciiJSON contains the given interface object.
    40  type AsciiJSON struct {
    41  	Data any
    42  }
    43  
    44  // PureJSON contains the given interface object.
    45  type PureJSON struct {
    46  	Data any
    47  }
    48  
    49  var (
    50  	jsonContentType      = []string{"application/json; charset=utf-8"}
    51  	jsonpContentType     = []string{"application/javascript; charset=utf-8"}
    52  	jsonASCIIContentType = []string{"application/json"}
    53  )
    54  
    55  // Render (JSON) writes data with custom ContentType.
    56  func (r JSON) Render(w http.ResponseWriter) error {
    57  	return WriteJSON(w, r.Data)
    58  }
    59  
    60  // WriteContentType (JSON) writes JSON ContentType.
    61  func (r JSON) WriteContentType(w http.ResponseWriter) {
    62  	writeContentType(w, jsonContentType)
    63  }
    64  
    65  // WriteJSON marshals the given interface object and writes it with custom ContentType.
    66  func WriteJSON(w http.ResponseWriter, obj any) error {
    67  	writeContentType(w, jsonContentType)
    68  	jsonBytes, err := json.Marshal(obj)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	_, err = w.Write(jsonBytes)
    73  	return err
    74  }
    75  
    76  // Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType.
    77  func (r IndentedJSON) Render(w http.ResponseWriter) error {
    78  	r.WriteContentType(w)
    79  	jsonBytes, err := json.MarshalIndent(r.Data, "", "    ")
    80  	if err != nil {
    81  		return err
    82  	}
    83  	_, err = w.Write(jsonBytes)
    84  	return err
    85  }
    86  
    87  // WriteContentType (IndentedJSON) writes JSON ContentType.
    88  func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
    89  	writeContentType(w, jsonContentType)
    90  }
    91  
    92  // Render (SecureJSON) marshals the given interface object and writes it with custom ContentType.
    93  func (r SecureJSON) Render(w http.ResponseWriter) error {
    94  	r.WriteContentType(w)
    95  	jsonBytes, err := json.Marshal(r.Data)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	// if the jsonBytes is array values
   100  	if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes,
   101  		bytesconv.StringToBytes("]")) {
   102  		if _, err = w.Write(bytesconv.StringToBytes(r.Prefix)); err != nil {
   103  			return err
   104  		}
   105  	}
   106  	_, err = w.Write(jsonBytes)
   107  	return err
   108  }
   109  
   110  // WriteContentType (SecureJSON) writes JSON ContentType.
   111  func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
   112  	writeContentType(w, jsonContentType)
   113  }
   114  
   115  // Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType.
   116  func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
   117  	r.WriteContentType(w)
   118  	ret, err := json.Marshal(r.Data)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	if r.Callback == "" {
   124  		_, err = w.Write(ret)
   125  		return err
   126  	}
   127  
   128  	callback := template.JSEscapeString(r.Callback)
   129  	if _, err = w.Write(bytesconv.StringToBytes(callback)); err != nil {
   130  		return err
   131  	}
   132  
   133  	if _, err = w.Write(bytesconv.StringToBytes("(")); err != nil {
   134  		return err
   135  	}
   136  
   137  	if _, err = w.Write(ret); err != nil {
   138  		return err
   139  	}
   140  
   141  	if _, err = w.Write(bytesconv.StringToBytes(");")); err != nil {
   142  		return err
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  // WriteContentType (JsonpJSON) writes Javascript ContentType.
   149  func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
   150  	writeContentType(w, jsonpContentType)
   151  }
   152  
   153  // Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType.
   154  func (r AsciiJSON) Render(w http.ResponseWriter) (err error) {
   155  	r.WriteContentType(w)
   156  	ret, err := json.Marshal(r.Data)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	var buffer bytes.Buffer
   162  	for _, r := range bytesconv.BytesToString(ret) {
   163  		cvt := string(r)
   164  		if r >= 128 {
   165  			cvt = fmt.Sprintf("\\u%04x", int64(r))
   166  		}
   167  		buffer.WriteString(cvt)
   168  	}
   169  
   170  	_, err = w.Write(buffer.Bytes())
   171  	return err
   172  }
   173  
   174  // WriteContentType (AsciiJSON) writes JSON ContentType.
   175  func (r AsciiJSON) WriteContentType(w http.ResponseWriter) {
   176  	writeContentType(w, jsonASCIIContentType)
   177  }
   178  
   179  // Render (PureJSON) writes custom ContentType and encodes the given interface object.
   180  func (r PureJSON) Render(w http.ResponseWriter) error {
   181  	r.WriteContentType(w)
   182  	encoder := json.NewEncoder(w)
   183  	encoder.SetEscapeHTML(false)
   184  	return encoder.Encode(r.Data)
   185  }
   186  
   187  // WriteContentType (PureJSON) writes custom ContentType.
   188  func (r PureJSON) WriteContentType(w http.ResponseWriter) {
   189  	writeContentType(w, jsonContentType)
   190  }
   191  

View as plain text