Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrUnexpectedEOF = &SyntaxError{"unexpected end of JSON input", -1} ErrInvalidHexEscape = &SyntaxError{"invalid hexadecimal escape sequence", -1} ErrStringEscape = &SyntaxError{"encountered an invalid escape sequence in a string", -1} )
Predefined errors
Functions ¶
func Decode ¶
Decode parses the JSON-encoded data and returns an interface value. The interface value could be one of these:
bool, for JSON booleans float64, for JSON numbers string, for JSON strings []interface{}, for JSON arrays map[string]interface{}, for JSON objects nil for JSON null
Note that the Decode is compatible with the the following insructions:
var v interface{} err := json.Unmarshal(data, &v)
Example ¶
package main import ( "fmt" "log" "github.com/a8m/djson" ) func main() { var data = []byte(`[ {"Name": "Platypus", "Order": "Monotremata"}, {"Name": "Quoll", "Order": "Dasyuromorphia"} ]`) val, err := djson.Decode(data) if err != nil { log.Fatal("error:", err) } fmt.Printf("%+v", val) // - Output: // [map[Name:Platypus Order:Monotremata] map[Name:Quoll Order:Dasyuromorphia]] }
Output:
func DecodeArray ¶
DecodeArray is the same as Decode but it returns []interface{}. You should use it to parse JSON arrays.
Example ¶
package main import ( "fmt" "log" "github.com/a8m/djson" ) func main() { var data = []byte(`[ "John", "Dan", "Kory", "Ariel" ]`) users, err := djson.DecodeArray(data) if err != nil { log.Fatal("error:", err) } for i, user := range users { fmt.Printf("[%d]: %v\n", i, user) } }
Output:
func DecodeObject ¶
DecodeObject is the same as Decode but it returns map[string]interface{}. You should use it to parse JSON objects.
Example ¶
Example that demonstrate the basic transformation I do on each incoming event. `lowerKeys` and `fixEncoding` are two generic methods, and they don't care about the schema. The three others(`maxMindGeo`, `dateFormat`and `refererURL`) process and extend the events dynamically based on the "APP_ID" field.
package main import ( "fmt" "log" "github.com/a8m/djson" ) func main() { var data = []byte(`{ "ID": 76523, "IP": "69.89.31.226" "APP_ID": "BD311", "Name": "Ariel", "Username": "a8m", "Score": 99, "Date": 1475332371532, "Image": { "Src": "images/67.png", "Height": 450, "Width": 370, "Alignment": "center" }, "RefererURL": "https://..." }`) event, err := djson.DecodeObject(data) if err != nil { log.Fatal("error:", err) } fmt.Printf("Value: %v", event) // Process the event // // lowerKeys(event) // fixEncoding(event) // dateFormat(event) // maxMindGeo(event) // refererURL(event) // // pipeline.Pipe(event) }
Output:
Types ¶
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder is the object that holds the state of the decoding
func NewDecoder ¶
NewDecoder creates new Decoder from the JSON-encoded data
func (*Decoder) AllocString ¶
func (d *Decoder) AllocString()
AllocString pre-allocates a string version of the data before starting to decode the data. It is used to make the decode operation faster(see below) by doing one allocation operation for string conversion(from bytes), and then uses "slicing" to create non-escaped strings in the "Decoder.string" method. However, string is a read-only slice, and since the slice references the original array, as long as the slice is kept around, the garbage collector can't release the array. For this reason, you want to use this method only when the Decoder's result is a "read-only" or you are adding more elements to it. see example below.
Here are the improvements:
small payload - 0.13~ time faster, does 0.45~ less memory allocations but the total number of bytes that are allocated is 0.03~ bigger medium payload - 0.16~ time faster, does 0.5~ less memory allocations but the total number of bytes that are allocated is 0.05~ bigger large payload - 0.13~ time faster, does 0.50~ less memory allocations but the total number of bytes that are allocated is 0.02~ bigger
Here is an example to illustrate when you don't want to use this method
str := fmt.Sprintf(`{"foo": "bar", "baz": "%s"}`, strings.Repeat("#", 1024 * 1024)) dec := djson.NewDecoder([]byte(str)) dec.AllocString() ev, err := dec.DecodeObject() // inpect memory stats here; MemStats.Alloc ~= 1M delete(ev, "baz") // or ev["baz"] = "qux" // inpect memory stats again; MemStats.Alloc ~= 1M // it means that the chunk that was located in the "baz" value is not freed
Example ¶
package main import ( "fmt" "log" "github.com/a8m/djson" ) func main() { var data = []byte(`{"event_type":"click","count":"93","userid":"4234A"}`) dec := djson.NewDecoder(data) dec.AllocString() val, err := dec.DecodeObject() if err != nil { log.Fatal("error:", err) } fmt.Printf("Value: %+v", val) // - Output: // map[count:93 userid:4234A event_type:click] }
Output:
func (*Decoder) Decode ¶
Decode parses the JSON-encoded data and returns an interface value. The interface value could be one of these:
bool, for JSON booleans float64, for JSON numbers string, for JSON strings []interface{}, for JSON arrays map[string]interface{}, for JSON objects nil for JSON null
Note that the Decode is compatible with the the following insructions:
var v interface{} err := json.Unmarshal(data, &v)
func (*Decoder) DecodeArray ¶
DecodeArray is the same as Decode but it returns []interface{}. You should use it to parse JSON arrays.
func (*Decoder) DecodeObject ¶
DecodeObject is the same as Decode but it returns map[string]interface{}. You should use it to parse JSON objects.
type SyntaxError ¶
type SyntaxError struct { Offset int // error occurred after reading Offset bytes // contains filtered or unexported fields }
A SyntaxError is a description of a JSON syntax error.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string