Initial QSfera import
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
package godata
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A response is a dictionary of keys to their corresponding fields. This will
|
||||
// be converted into a JSON dictionary in the response to the web client.
|
||||
type GoDataResponse struct {
|
||||
Fields map[string]*GoDataResponseField
|
||||
}
|
||||
|
||||
// Serialize the result as JSON for sending to the client. If an error
|
||||
// occurs during the serialization, it will be returned.
|
||||
func (r *GoDataResponse) Json() ([]byte, error) {
|
||||
result, err := prepareJsonDict(r.Fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// A response that is a primitive JSON type or a list or a dictionary. When
|
||||
// writing to JSON, it is automatically mapped from the Go type to a suitable
|
||||
// JSON data type. Any type can be used, but if the data type is not supported
|
||||
// for serialization, then an error is thrown.
|
||||
type GoDataResponseField struct {
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Convert the response field to a JSON serialized form. If the type is not
|
||||
// string, []byte, int, float64, map[string]*GoDataResponseField, or
|
||||
// []*GoDataResponseField, then an error will be thrown.
|
||||
func (f *GoDataResponseField) Json() ([]byte, error) {
|
||||
switch f.Value.(type) {
|
||||
case string:
|
||||
return prepareJsonString([]byte(f.Value.(string)))
|
||||
case []byte:
|
||||
return prepareJsonString(f.Value.([]byte))
|
||||
case int:
|
||||
return []byte(strconv.Itoa(f.Value.(int))), nil
|
||||
case float64:
|
||||
return []byte(strconv.FormatFloat(f.Value.(float64), 'f', -1, 64)), nil
|
||||
case map[string]*GoDataResponseField:
|
||||
return prepareJsonDict(f.Value.(map[string]*GoDataResponseField))
|
||||
case []*GoDataResponseField:
|
||||
return prepareJsonList(f.Value.([]*GoDataResponseField))
|
||||
default:
|
||||
return nil, InternalServerError("Response field type not recognized.")
|
||||
}
|
||||
}
|
||||
|
||||
func prepareJsonString(s []byte) ([]byte, error) {
|
||||
// escape double quotes
|
||||
s = bytes.Replace(s, []byte("\""), []byte("\\\""), -1)
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('"')
|
||||
buf.Write(s)
|
||||
buf.WriteByte('"')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func prepareJsonDict(d map[string]*GoDataResponseField) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('{')
|
||||
count := 0
|
||||
for k, v := range d {
|
||||
buf.WriteByte('"')
|
||||
buf.Write([]byte(k))
|
||||
buf.WriteByte('"')
|
||||
buf.WriteByte(':')
|
||||
field, err := v.Json()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(field)
|
||||
count++
|
||||
if count < len(d) {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func prepareJsonList(l []*GoDataResponseField) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('[')
|
||||
count := 0
|
||||
for _, v := range l {
|
||||
field, err := v.Json()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(field)
|
||||
count++
|
||||
if count < len(l) {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user