mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
348 lines
9.8 KiB
Go
348 lines
9.8 KiB
Go
// +test OMIT
|
|
|
|
// note - "// Output:" is a key for "go test" to match function ouput with the lines that follow.
|
|
// It is also use by "godoc" to build the Output block of the function / method documentation.
|
|
// To skip processing Example* functions, use: go test -run "Test*"
|
|
// or make sure example function output matches // Output: documentation EXACTLY.
|
|
|
|
package mxj_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"gitee.com/johng/gf/third/github.com/clbanning/mxj"
|
|
"io"
|
|
)
|
|
|
|
func ExampleHandleXmlReader() {
|
|
/*
|
|
Bulk processing XML to JSON seems to be a common requirement.
|
|
See: bulk_test.go for working example.
|
|
Run "go test" in package directory then scroll back to find output.
|
|
|
|
The logic is as follows.
|
|
|
|
// need somewhere to write the JSON.
|
|
var jsonWriter io.Writer
|
|
|
|
// probably want to log any errors in reading the XML stream
|
|
var xmlErrLogger io.Writer
|
|
|
|
// func to handle Map value from XML Reader
|
|
func maphandler(m mxj.Map) bool {
|
|
// marshal Map as JSON
|
|
jsonVal, err := m.Json()
|
|
if err != nil {
|
|
// log error
|
|
return false // stops further processing of XML Reader
|
|
}
|
|
|
|
// write JSON somewhere
|
|
_, err = jsonWriter.Write(jsonVal)
|
|
if err != nil {
|
|
// log error
|
|
return false // stops further processing of XML Reader
|
|
}
|
|
|
|
// continue - get next XML from Reader
|
|
return true
|
|
}
|
|
|
|
// func to handle error from unmarshaling XML Reader
|
|
func errhandler(errVal error) bool {
|
|
// log error somewhere
|
|
_, err := xmlErrLogger.Write([]byte(errVal.Error()))
|
|
if err != nil {
|
|
// log error
|
|
return false // stops further processing of XML Reader
|
|
}
|
|
|
|
// continue processing
|
|
return true
|
|
}
|
|
|
|
// func that starts bulk processing of the XML
|
|
...
|
|
// set up io.Reader for XML data - perhaps an os.File
|
|
...
|
|
err := mxj.HandleXmlReader(xmlReader, maphandler, errhandler)
|
|
if err != nil {
|
|
// handle error
|
|
}
|
|
...
|
|
*/
|
|
}
|
|
|
|
func ExampleHandleXmlReaderRaw() {
|
|
/*
|
|
See: bulkraw_test.go for working example.
|
|
Run "go test" in package directory then scroll back to find output.
|
|
|
|
Basic logic for bulk XML to JSON processing is in HandleXmlReader example;
|
|
the only major difference is in handler function signatures so they are passed
|
|
the raw XML. (Read documentation on NewXmlReader regarding performance.)
|
|
*/
|
|
}
|
|
|
|
func ExampleHandleJsonReader() {
|
|
/*
|
|
See: bulk_test.go for working example.
|
|
Run "go test" in package directory then scroll back to find output.
|
|
|
|
Basic logic for bulk JSON to XML processing is similar to that for
|
|
bulk XML to JSON processing as outlined in the HandleXmlReader example.
|
|
The test case is also a good example.
|
|
*/
|
|
}
|
|
|
|
func ExampleHandleJsonReaderRaw() {
|
|
/*
|
|
See: bulkraw_test.go for working example.
|
|
Run "go test" in package directory then scroll back to find output.
|
|
|
|
Basic logic for bulk JSON to XML processing is similar to that for
|
|
bulk XML to JSON processing as outlined in the HandleXmlReader example.
|
|
The test case is also a good example.
|
|
*/
|
|
}
|
|
|
|
/*
|
|
func ExampleNewMapXmlReaderRaw() {
|
|
// in an http.Handler
|
|
|
|
mapVal, raw, err := mxj.NewMapXmlReader(req.Body)
|
|
if err != nil {
|
|
// handle error
|
|
}
|
|
logger.Print(string(*raw))
|
|
// do something with mapVal
|
|
|
|
}
|
|
*/
|
|
|
|
func ExampleNewMapStruct() {
|
|
type str struct {
|
|
IntVal int `structs:"int"`
|
|
StrVal string `structs:"str"`
|
|
FloatVal float64 `structs:"float"`
|
|
BoolVal bool `structs:"bool"`
|
|
private string
|
|
}
|
|
strVal := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"}
|
|
|
|
mapVal, merr := mxj.NewMapStruct(strVal)
|
|
if merr != nil {
|
|
// handle error
|
|
}
|
|
|
|
fmt.Printf("strVal: %#v\n", strVal)
|
|
fmt.Printf("mapVal: %#v\n", mapVal)
|
|
// Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name.
|
|
|
|
// NoFail output:
|
|
// strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"}
|
|
// mapVal: mxj.Map{"float":3.14159, "bool":true, "int":4, "str":"now's the time"}
|
|
}
|
|
|
|
func ExampleMap_Struct() {
|
|
type str struct {
|
|
IntVal int `json:"int"`
|
|
StrVal string `json:"str"`
|
|
FloatVal float64 `json:"float"`
|
|
BoolVal bool `json:"bool"`
|
|
private string
|
|
}
|
|
|
|
mapVal := mxj.Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true, "private": "Somewhere over the rainbow"}
|
|
|
|
var strVal str
|
|
mverr := mapVal.Struct(&strVal)
|
|
if mverr != nil {
|
|
// handle error
|
|
}
|
|
|
|
fmt.Printf("mapVal: %#v\n", mapVal)
|
|
fmt.Printf("strVal: %#v\n", strVal)
|
|
// Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name.
|
|
|
|
// Unordered output:
|
|
// mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true, "private":"Somewhere over the rainbow"}
|
|
// strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""}
|
|
}
|
|
|
|
func ExampleMap_ValuesForPath() {
|
|
// a snippet from examples/gonuts1.go
|
|
// How to compensate for irregular tag labels in data.
|
|
// Need to extract from an XML stream the values for "netid" and "idnet".
|
|
// Solution: use a wildcard path "data.*" to anonymize the "netid" and "idnet" tags.
|
|
|
|
var msg1 = []byte(`
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<data>
|
|
<netid>
|
|
<disable>no</disable>
|
|
<text1>default:text</text1>
|
|
<word1>default:word</word1>
|
|
</netid>
|
|
</data>
|
|
`)
|
|
|
|
var msg2 = []byte(`
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<data>
|
|
<idnet>
|
|
<disable>yes</disable>
|
|
<text1>default:text</text1>
|
|
<word1>default:word</word1>
|
|
</idnet>
|
|
</data>
|
|
`)
|
|
|
|
// let's create a message stream
|
|
buf := new(bytes.Buffer)
|
|
// load a couple of messages into it
|
|
_, _ = buf.Write(msg1)
|
|
_, _ = buf.Write(msg2)
|
|
|
|
n := 0
|
|
for {
|
|
n++
|
|
// Read the stream as Map values - quit on io.EOF.
|
|
// Get the raw XML as well as the Map value.
|
|
m, merr := mxj.NewMapXmlReader(buf)
|
|
if merr != nil && merr != io.EOF {
|
|
// handle error - for demo we just print it and continue
|
|
fmt.Printf("msg: %d - merr: %s\n", n, merr.Error())
|
|
continue
|
|
} else if merr == io.EOF {
|
|
break
|
|
}
|
|
|
|
// get the values for "netid" or "idnet" key using path == "data.*"
|
|
values, _ := m.ValuesForPath("data.*")
|
|
fmt.Println("\nmsg:", n, "> path == data.* - got array of values, len:", len(values))
|
|
for i, val := range values {
|
|
fmt.Println("ValuesForPath result array member -", i, ":", val)
|
|
fmt.Println(" k:v pairs for array member:", i)
|
|
for key, val := range val.(map[string]interface{}) {
|
|
// You'd probably want to process the value, as appropriate.
|
|
// Here we just print it out.
|
|
fmt.Println("\t\t", key, ":", val)
|
|
}
|
|
}
|
|
}
|
|
// NoFail output:
|
|
// msg: 1 > path == data.* - got array of values, len: 1
|
|
// ValuesForPath result array member - 0 : map[disable:no text1:default:text word1:default:word]
|
|
// k:v pairs for array member: 0
|
|
// disable : no
|
|
// text1 : default:text
|
|
// word1 : default:word
|
|
//
|
|
// msg: 2 > path == data.* - got array of values, len: 1
|
|
// ValuesForPath result array member - 0 : map[disable:yes text1:default:text word1:default:word]
|
|
// k:v pairs for array member: 0
|
|
// disable : yes
|
|
// text1 : default:text
|
|
// word1 : default:word
|
|
}
|
|
|
|
func ExampleMap_UpdateValuesForPath() {
|
|
/*
|
|
|
|
var biblioDoc = []byte(`
|
|
<biblio>
|
|
<author>
|
|
<name>William Gaddis</name>
|
|
<books>
|
|
<book>
|
|
<title>The Recognitions</title>
|
|
<date>1955</date>
|
|
<review>A novel that changed the face of American literature.</review>
|
|
</book>
|
|
<book>
|
|
<title>JR</title>
|
|
<date>1975</date>
|
|
<review>Winner of National Book Award for Fiction.</review>
|
|
</book>
|
|
</books>
|
|
</author>
|
|
</biblio>`)
|
|
|
|
...
|
|
m, merr := mxj.NewMapXml(biblioDoc)
|
|
if merr != nil {
|
|
// handle error
|
|
}
|
|
|
|
// change 'review' for a book
|
|
count, err := m.UpdateValuesForPath("review:National Book Award winner." "*.*.*.*", "title:JR")
|
|
if err != nil {
|
|
// handle error
|
|
}
|
|
...
|
|
|
|
// change 'date' value from string type to float64 type
|
|
// Note: the following is equivalent to m, merr := NewMapXml(biblioDoc, mxj.Cast).
|
|
path := m.PathForKeyShortest("date")
|
|
v, err := m.ValuesForPath(path)
|
|
if err != nil {
|
|
// handle error
|
|
}
|
|
var total int
|
|
for _, vv := range v {
|
|
oldVal := "date:" + vv.(string)
|
|
newVal := "date:" + vv.(string) + ":num"
|
|
n, err := m.UpdateValuesForPath(newVal, path, oldVal)
|
|
if err != nil {
|
|
// handle error
|
|
}
|
|
total += n
|
|
}
|
|
...
|
|
*/
|
|
}
|
|
|
|
func ExampleMap_Copy() {
|
|
// Hand-crafted Map values that include structures do NOT Copy() as expected,
|
|
// since to simulate a deep copy the original Map value is JSON encoded then decoded.
|
|
|
|
type str struct {
|
|
IntVal int `json:"int"`
|
|
StrVal string `json:"str"`
|
|
FloatVal float64 `json:"float"`
|
|
BoolVal bool `json:"bool"`
|
|
private string
|
|
}
|
|
s := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"}
|
|
m := make(map[string]interface{}, 0)
|
|
m["struct"] = interface{}(s)
|
|
m["struct_ptr"] = interface{}(&s)
|
|
m["misc"] = interface{}(`Now is the time`)
|
|
|
|
mv := mxj.Map(m)
|
|
cp, _ := mv.Copy()
|
|
|
|
fmt.Printf("mv:\n%s\n", mv.StringIndent(2))
|
|
fmt.Printf("cp:\n%s\n", cp.StringIndent(2))
|
|
|
|
// NoFail output:
|
|
// mv:
|
|
// misc : [string] Now is the time
|
|
// struct : [mxj_test.str] {IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue}
|
|
// struct_ptr : [*mxj_test.str] &{IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue}
|
|
// cp:
|
|
// misc : [string] Now is the time
|
|
// struct :
|
|
// bool : [bool] true
|
|
// float : [float64] 3.14159
|
|
// int : [float64] 4
|
|
// str : [string] now's the time
|
|
// struct_ptr :
|
|
// bool : [bool] true
|
|
// float : [float64] 3.14159
|
|
// int : [float64] 4
|
|
// str : [string] now's the time
|
|
//
|
|
}
|