github.com/CiscoM31/godata@v1.0.10/response_model.go (about)

     1  package godata
     2  
     3  import (
     4  	"bytes"
     5  	"strconv"
     6  )
     7  
     8  // A response is a dictionary of keys to their corresponding fields. This will
     9  // be converted into a JSON dictionary in the response to the web client.
    10  type GoDataResponse struct {
    11  	Fields map[string]*GoDataResponseField
    12  }
    13  
    14  // Serialize the result as JSON for sending to the client. If an error
    15  // occurs during the serialization, it will be returned.
    16  func (r *GoDataResponse) Json() ([]byte, error) {
    17  	result, err := prepareJsonDict(r.Fields)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	return result, nil
    22  }
    23  
    24  // A response that is a primitive JSON type or a list or a dictionary. When
    25  // writing to JSON, it is automatically mapped from the Go type to a suitable
    26  // JSON data type. Any type can be used, but if the data type is not supported
    27  // for serialization, then an error is thrown.
    28  type GoDataResponseField struct {
    29  	Value interface{}
    30  }
    31  
    32  // Convert the response field to a JSON serialized form. If the type is not
    33  // string, []byte, int, float64, map[string]*GoDataResponseField, or
    34  // []*GoDataResponseField, then an error will be thrown.
    35  func (f *GoDataResponseField) Json() ([]byte, error) {
    36  	switch f.Value.(type) {
    37  	case string:
    38  		return prepareJsonString([]byte(f.Value.(string)))
    39  	case []byte:
    40  		return prepareJsonString(f.Value.([]byte))
    41  	case int:
    42  		return []byte(strconv.Itoa(f.Value.(int))), nil
    43  	case float64:
    44  		return []byte(strconv.FormatFloat(f.Value.(float64), 'f', -1, 64)), nil
    45  	case map[string]*GoDataResponseField:
    46  		return prepareJsonDict(f.Value.(map[string]*GoDataResponseField))
    47  	case []*GoDataResponseField:
    48  		return prepareJsonList(f.Value.([]*GoDataResponseField))
    49  	default:
    50  		return nil, InternalServerError("Response field type not recognized.")
    51  	}
    52  }
    53  
    54  func prepareJsonString(s []byte) ([]byte, error) {
    55  	// escape double quotes
    56  	s = bytes.Replace(s, []byte("\""), []byte("\\\""), -1)
    57  	var buf bytes.Buffer
    58  	buf.WriteByte('"')
    59  	buf.Write(s)
    60  	buf.WriteByte('"')
    61  	return buf.Bytes(), nil
    62  }
    63  
    64  func prepareJsonDict(d map[string]*GoDataResponseField) ([]byte, error) {
    65  	var buf bytes.Buffer
    66  	buf.WriteByte('{')
    67  	count := 0
    68  	for k, v := range d {
    69  		buf.WriteByte('"')
    70  		buf.Write([]byte(k))
    71  		buf.WriteByte('"')
    72  		buf.WriteByte(':')
    73  		field, err := v.Json()
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  		buf.Write(field)
    78  		count++
    79  		if count < len(d) {
    80  			buf.WriteByte(',')
    81  		}
    82  	}
    83  	buf.WriteByte('}')
    84  	return buf.Bytes(), nil
    85  }
    86  
    87  func prepareJsonList(l []*GoDataResponseField) ([]byte, error) {
    88  	var buf bytes.Buffer
    89  	buf.WriteByte('[')
    90  	count := 0
    91  	for _, v := range l {
    92  		field, err := v.Json()
    93  		if err != nil {
    94  			return nil, err
    95  		}
    96  		buf.Write(field)
    97  		count++
    98  		if count < len(l) {
    99  			buf.WriteByte(',')
   100  		}
   101  	}
   102  	buf.WriteByte(']')
   103  	return buf.Bytes(), nil
   104  }