Compare commits
No commits in common. "fe2cdb4f212df4704f82c7aa456ae134d26d79ff" and "41f2436f9fdebabf80704bbd50fae206781cba82" have entirely different histories.
fe2cdb4f21
...
41f2436f9f
@ -101,12 +101,6 @@ r.Headers().ConentType_textPlain()
|
|||||||
//r.Headers().Set("Content-Type","text/plain; charset=utf-8")
|
//r.Headers().Set("Content-Type","text/plain; charset=utf-8")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2.4.5 忽略指定请求头
|
|
||||||
在默认情况下,`Content-Type`将被自动添加到请求头中,但对于某些场景来说这会导致请求失败。使用下面的方法可以忽略指定的请求头
|
|
||||||
```go
|
|
||||||
r.Headers().Omit("Content-Type")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 添加queryParams
|
### 2.5 添加queryParams
|
||||||
#### 2.5.1 单个赋值
|
#### 2.5.1 单个赋值
|
||||||
```go
|
```go
|
||||||
|
14
body.go
14
body.go
@ -7,9 +7,7 @@
|
|||||||
|
|
||||||
package simpleRequest
|
package simpleRequest
|
||||||
|
|
||||||
import (
|
import "mime/multipart"
|
||||||
"mime/multipart"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EntryMark 请求体条目标记,用于标记输入的body内容格式
|
// EntryMark 请求体条目标记,用于标记输入的body内容格式
|
||||||
type EntryMark string
|
type EntryMark string
|
||||||
@ -59,23 +57,13 @@ func (s *BodyConf) SetModel(model any) *BodyConf {
|
|||||||
s.simpleReq.BodyEntries[ModelEntryType.string()] = model
|
s.simpleReq.BodyEntries[ModelEntryType.string()] = model
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加上传文件
|
|
||||||
func (s *BodyConf) SetFromDataFile(key, filePath string) *BodyConf {
|
func (s *BodyConf) SetFromDataFile(key, filePath string) *BodyConf {
|
||||||
s.simpleReq.BodyEntryMark = MultipartEntryType
|
s.simpleReq.BodyEntryMark = MultipartEntryType
|
||||||
s.simpleReq.BodyEntries[FormFilePathKey.string()+key] = filePath
|
s.simpleReq.BodyEntries[FormFilePathKey.string()+key] = filePath
|
||||||
if s.simpleReq.headers.Get(hdrContentTypeKey) == "" {
|
|
||||||
s.simpleReq.headers.Set(hdrContentTypeKey, formDataType)
|
|
||||||
}
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加文件,适用于服务端文件转发场景,比如直接从c.FormFile("file")中获取FileHeader对象转发即可
|
|
||||||
func (s *BodyConf) SetFromDataMultipartFile(key string, multFile *multipart.FileHeader) *BodyConf {
|
func (s *BodyConf) SetFromDataMultipartFile(key string, multFile *multipart.FileHeader) *BodyConf {
|
||||||
s.simpleReq.BodyEntryMark = MultipartEntryType
|
s.simpleReq.BodyEntryMark = MultipartEntryType
|
||||||
s.simpleReq.BodyEntries[key] = multFile
|
s.simpleReq.BodyEntries[key] = multFile
|
||||||
if s.simpleReq.headers.Get(hdrContentTypeKey) == "" {
|
|
||||||
s.simpleReq.headers.Set(hdrContentTypeKey, formDataType)
|
|
||||||
}
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dorlolo/simpleRequest"
|
"github.com/dorlolo/simpleRequest"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -51,7 +50,7 @@ func TestRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 测试content-type 为 multipart/form-data格式的数据请求
|
// 测试content-type 为 multipart/form-data格式的数据请求
|
||||||
func TestAuth_formData(t *testing.T) {
|
func TestAuth_fotmData(t *testing.T) {
|
||||||
req := simpleRequest.NewRequest()
|
req := simpleRequest.NewRequest()
|
||||||
req.Headers().ConentType_formData()
|
req.Headers().ConentType_formData()
|
||||||
req.Headers().SetRandomUerAgent()
|
req.Headers().SetRandomUerAgent()
|
||||||
@ -133,24 +132,3 @@ func TestTextPlain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 阿里云Oss文件上传示例
|
|
||||||
func TestUploadFileToOss(t *testing.T) {
|
|
||||||
var signedUrl = "" //STS授权url
|
|
||||||
var xOssCallback = "" //回调信息
|
|
||||||
var req = simpleRequest.NewRequest()
|
|
||||||
req.Headers().
|
|
||||||
Sets(map[string]string{
|
|
||||||
"X-Oss-Callback": xOssCallback,
|
|
||||||
})
|
|
||||||
|
|
||||||
fileData, err := os.ReadFile("./CHANGELOG.MD")
|
|
||||||
req.Body().SetBytes(fileData)
|
|
||||||
|
|
||||||
body, err := req.PUT(signedUrl)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(string(body))
|
|
||||||
}
|
|
||||||
|
20
headers.go
20
headers.go
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
*FileName: header.go
|
||||||
|
*Author: JJXu
|
||||||
|
*CreateTime: 2022/3/1 下午9:44
|
||||||
|
*Description:
|
||||||
|
*/
|
||||||
|
|
||||||
package simpleRequest
|
package simpleRequest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -63,13 +70,7 @@ func (s *HeadersConf) Add(header, value string) *HeadersConf {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Omit Use to disable automatically generated request headers ,some like Content_Type.
|
//一般用不到
|
||||||
func (s *HeadersConf) Omit(keys ...string) *HeadersConf {
|
|
||||||
s.simpleReq.omitHeaderKeys = append(s.simpleReq.omitHeaderKeys, keys...)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
//deprecated
|
|
||||||
//func (s *HeadersConf) Values(keys string) *HeadersConf {
|
//func (s *HeadersConf) Values(keys string) *HeadersConf {
|
||||||
// s.simpleReq.headers.Values(keys)
|
// s.simpleReq.headers.Values(keys)
|
||||||
// return s
|
// return s
|
||||||
@ -109,6 +110,11 @@ func (s *HeadersConf) ConentType_charsetUtf8() *HeadersConf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeadersConf) ConentType_formData() *HeadersConf {
|
func (s *HeadersConf) ConentType_formData() *HeadersConf {
|
||||||
|
//tmp := url.Values{}
|
||||||
|
|
||||||
|
//for k, v := range s.simpleReq.BodyEntry {
|
||||||
|
// tmp.Add(k, fmt.Sprintf("%v", v))
|
||||||
|
//}
|
||||||
s.simpleReq.headers.Set(hdrContentTypeKey, formDataType)
|
s.simpleReq.headers.Set(hdrContentTypeKey, formDataType)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
64
parser.go
64
parser.go
@ -9,8 +9,6 @@ package simpleRequest
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
@ -18,11 +16,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 通用类型解析器
|
|
||||||
var bodyEntryParsers = map[string]IBodyEntryParser{
|
var bodyEntryParsers = map[string]IBodyEntryParser{
|
||||||
jsonContentType: new(JsonParser),
|
jsonContentType: new(JsonParser),
|
||||||
formDataType: new(FormDataParser),
|
formDataType: new(FormDataParser),
|
||||||
xmlDataType: new(XmlParser),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type IBodyEntryParser interface {
|
type IBodyEntryParser interface {
|
||||||
@ -92,31 +88,32 @@ func (f *FormDataParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any)
|
|||||||
}
|
}
|
||||||
func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentType string) {
|
func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentType string) {
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
formWriter := multipart.NewWriter(body)
|
writer := multipart.NewWriter(body)
|
||||||
for k, sv := range BodyEntry {
|
for k, sv := range BodyEntry {
|
||||||
if strings.Contains(k, FormFilePathKey.string()) {
|
if strings.Contains(k, FormFilePathKey.string()) {
|
||||||
fieldName := k[len(FormFilePathKey):]
|
key := k[len(FormFilePathKey):]
|
||||||
fp := sv.(string)
|
path := sv.(string)
|
||||||
filename := filepath.Base(fp)
|
filename := filepath.Base(path)
|
||||||
//way1
|
filePart, _ := writer.CreateFormFile(key, filename)
|
||||||
filePart, _ := formWriter.CreateFormFile(fieldName, filename)
|
content, err := os.ReadFile(path)
|
||||||
content, err := os.ReadFile(fp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
_, _ = filePart.Write(content)
|
_, _ = filePart.Write(content)
|
||||||
} else {
|
} else {
|
||||||
switch multValue := sv.(type) {
|
switch sv.(type) {
|
||||||
case string:
|
case string:
|
||||||
_ = formWriter.WriteField(k, multValue)
|
strSv, _ := sv.(string)
|
||||||
|
_ = writer.WriteField(k, strSv)
|
||||||
case []string:
|
case []string:
|
||||||
sss, _ := sv.([]string)
|
sss, _ := sv.([]string)
|
||||||
for _, v := range sss {
|
for _, v := range sss {
|
||||||
_ = formWriter.WriteField(k, v)
|
_ = writer.WriteField(k, v)
|
||||||
}
|
}
|
||||||
case *multipart.FileHeader:
|
case *multipart.FileHeader:
|
||||||
filePart, _ := formWriter.CreateFormFile(k, multValue.Filename)
|
file, _ := sv.(*multipart.FileHeader)
|
||||||
src, err := multValue.Open()
|
filePart, _ := writer.CreateFormFile(k, file.Filename)
|
||||||
|
src, err := file.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
return
|
return
|
||||||
@ -127,44 +124,13 @@ func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentTy
|
|||||||
panic(err)
|
panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case []byte:
|
|
||||||
formWriter.WriteField(k, string(multValue))
|
|
||||||
case int:
|
|
||||||
formWriter.WriteField(k, fmt.Sprintf("%v", multValue))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
err := formWriter.Close()
|
err := writer.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return body, formWriter.FormDataContentType()
|
return body, writer.FormDataContentType()
|
||||||
}
|
|
||||||
|
|
||||||
type XmlParser struct{}
|
|
||||||
|
|
||||||
func (f XmlParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any) (body io.Reader) {
|
|
||||||
switch bodyType {
|
|
||||||
case MapEntryType:
|
|
||||||
xmlData, err := xml.Marshal(BodyEntry[bodyType.string()])
|
|
||||||
if err == nil {
|
|
||||||
return bytes.NewReader(xmlData)
|
|
||||||
} else {
|
|
||||||
return strings.NewReader("")
|
|
||||||
}
|
|
||||||
case ModelEntryType:
|
|
||||||
xmlData, err := xml.Marshal(BodyEntry[bodyType.string()])
|
|
||||||
if err == nil {
|
|
||||||
return bytes.NewReader(xmlData)
|
|
||||||
} else {
|
|
||||||
return strings.NewReader("")
|
|
||||||
}
|
|
||||||
case StringEntryType:
|
|
||||||
return strings.NewReader(BodyEntry[StringEntryType.string()].(string))
|
|
||||||
case BytesEntryType:
|
|
||||||
return bytes.NewReader(BodyEntry[BytesEntryType.string()].([]byte))
|
|
||||||
default:
|
|
||||||
return strings.NewReader("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
package simpleRequest
|
package simpleRequest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@ -46,7 +46,6 @@ type SimpleRequest struct {
|
|||||||
queryParams url.Values
|
queryParams url.Values
|
||||||
body io.Reader
|
body io.Reader
|
||||||
headers http.Header
|
headers http.Header
|
||||||
omitHeaderKeys []string
|
|
||||||
transport *http.Transport
|
transport *http.Transport
|
||||||
|
|
||||||
BodyEntryMark EntryMark
|
BodyEntryMark EntryMark
|
||||||
@ -151,8 +150,6 @@ func (s *SimpleRequest) do(request *http.Request) (body []byte, err error) {
|
|||||||
//v0.0.2更新,将request和response内容返回,便于用户进行分析 JJXu 03-11-2022
|
//v0.0.2更新,将request和response内容返回,便于用户进行分析 JJXu 03-11-2022
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
s.Response = *resp
|
s.Response = *resp
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if request != nil {
|
if request != nil {
|
||||||
s.Request = *request
|
s.Request = *request
|
||||||
@ -160,7 +157,7 @@ func (s *SimpleRequest) do(request *http.Request) (body []byte, err error) {
|
|||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
//3.2 获取数据
|
//3.2 获取数据
|
||||||
body, err = io.ReadAll(resp.Body)
|
body, err = ioutil.ReadAll(resp.Body)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,13 +180,9 @@ func (s *SimpleRequest) LaunchTo(urls, method string) (body []byte, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//headers
|
//headers
|
||||||
//for k := range s.headers {
|
for k := range s.headers {
|
||||||
// r.Header[k] = append(r.Header[k], s.headers[k]...)
|
r.Header[k] = append(r.Header[k], s.headers[k]...)
|
||||||
// s.headers.Del(k)
|
s.headers.Del(k)
|
||||||
//}
|
|
||||||
r.Header = s.headers
|
|
||||||
for _, k := range s.omitHeaderKeys {
|
|
||||||
r.Header.Del(k)
|
|
||||||
}
|
}
|
||||||
//queryParams
|
//queryParams
|
||||||
if r.URL.RawQuery != "" {
|
if r.URL.RawQuery != "" {
|
||||||
@ -251,7 +244,6 @@ func (s *SimpleRequest) TRACE(url string) (body []byte, err error) {
|
|||||||
// 这里数据
|
// 这里数据
|
||||||
func (s *SimpleRequest) initBody() {
|
func (s *SimpleRequest) initBody() {
|
||||||
contentTypeData := s.headers.Get(hdrContentTypeKey)
|
contentTypeData := s.headers.Get(hdrContentTypeKey)
|
||||||
if contentTypeData != "" {
|
|
||||||
switch {
|
switch {
|
||||||
case IsJSONType(contentTypeData):
|
case IsJSONType(contentTypeData):
|
||||||
var parser, ok = s.bodyEntryParsers[jsonContentType]
|
var parser, ok = s.bodyEntryParsers[jsonContentType]
|
||||||
@ -288,8 +280,8 @@ func (s *SimpleRequest) initBody() {
|
|||||||
}
|
}
|
||||||
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
|
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
|
||||||
|
|
||||||
case strings.Contains(contentTypeData, "form-urlencoded"):
|
case contentTypeData == "" || strings.Contains(contentTypeData, "form-urlencoded"):
|
||||||
//default header type is "x-www-form-urlencoded"
|
//默认为x-www-form-urlencoded格式
|
||||||
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
|
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
|
||||||
if !ok {
|
if !ok {
|
||||||
tmpData := url.Values{}
|
tmpData := url.Values{}
|
||||||
@ -302,39 +294,11 @@ func (s *SimpleRequest) initBody() {
|
|||||||
}
|
}
|
||||||
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
|
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
|
||||||
default:
|
default:
|
||||||
//todo Automatically determine the data type
|
//todo 自动判断数据类型
|
||||||
tmpData := url.Values{}
|
tmpData := url.Values{}
|
||||||
for k, v := range tmpData {
|
for k, v := range tmpData {
|
||||||
if strings.HasPrefix(k, FormFilePathKey.string()) {
|
|
||||||
k = k[len(FormFilePathKey):]
|
|
||||||
}
|
|
||||||
tmpData.Set(k, fmt.Sprintf("%v", v))
|
tmpData.Set(k, fmt.Sprintf("%v", v))
|
||||||
}
|
}
|
||||||
s.body = strings.NewReader(tmpData.Encode())
|
s.body = strings.NewReader(tmpData.Encode())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
switch s.BodyEntryMark {
|
|
||||||
case BytesEntryType:
|
|
||||||
s.body = bytes.NewReader(s.BodyEntries[BytesEntryType.string()].([]byte))
|
|
||||||
case StringEntryType:
|
|
||||||
s.body = strings.NewReader(s.BodyEntries[BytesEntryType.string()].(string))
|
|
||||||
default:
|
|
||||||
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
|
|
||||||
if !ok {
|
|
||||||
tmpData := url.Values{}
|
|
||||||
for k, v := range s.BodyEntries {
|
|
||||||
if strings.HasPrefix(k, FormFilePathKey.string()) {
|
|
||||||
k = k[len(FormFilePathKey):]
|
|
||||||
}
|
|
||||||
tmpData.Set(k, fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
s.body = strings.NewReader(tmpData.Encode())
|
|
||||||
s.Headers().ConentType_formUrlencoded()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
95
utils.go
95
utils.go
@ -7,11 +7,6 @@
|
|||||||
|
|
||||||
package simpleRequest
|
package simpleRequest
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsJSONType(ct string) bool {
|
func IsJSONType(ct string) bool {
|
||||||
return jsonCheck.MatchString(ct)
|
return jsonCheck.MatchString(ct)
|
||||||
}
|
}
|
||||||
@ -20,93 +15,3 @@ func IsJSONType(ct string) bool {
|
|||||||
func IsXMLType(ct string) bool {
|
func IsXMLType(ct string) bool {
|
||||||
return xmlCheck.MatchString(ct)
|
return xmlCheck.MatchString(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsInArray(arr []string, str string) bool {
|
|
||||||
for _, v := range arr {
|
|
||||||
if v == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type xmlMapEntry struct {
|
|
||||||
XMLName xml.Name
|
|
||||||
Value interface{} `xml:",chardata"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// func MapToXml(data map[string]any) ([]byte, error) {
|
|
||||||
// xmlData, err := mapToXML(data)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// return xml.MarshalIndent(xmlData, "", " ")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func mapToXML(m map[string]interface{}) (xmlMap map[string]xmlMapEntry, err error) {
|
|
||||||
// if len(m) > 1 {
|
|
||||||
// return nil, errors.New("xml format must have a root name,the map value must like this: map[string]interface{}{\"rootName\":map[string]interface{}{}}")
|
|
||||||
// }
|
|
||||||
// xmlMap = make(map[string]xmlMapEntry)
|
|
||||||
// var rootName string
|
|
||||||
// for root, data := range m {
|
|
||||||
// rootName = root
|
|
||||||
// for k, v := range data.(map[string]interface{}) {
|
|
||||||
// switch typeV := v.(type) {
|
|
||||||
// case map[string]interface{}:
|
|
||||||
// subXmlMap, err := mapToXML(typeV)
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// default:
|
|
||||||
// entry := xmlMapEntry{XMLName: xml.Name{Local: k}, Value: v}
|
|
||||||
// xmlMap[k] = entry
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// xmlData := struct {
|
|
||||||
// XMLName xml.Name
|
|
||||||
// Data []xmlMapEntry `xml:",any"`
|
|
||||||
// }{
|
|
||||||
// XMLName: xml.Name{Local: rootName},
|
|
||||||
// Data: make([]xmlMapEntry, 0, len(xmlMap)),
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for _, v := range xmlMap {
|
|
||||||
// xmlData.Data = append(xmlData.Data, v)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return xml.MarshalIndent(xmlData, "", " ")
|
|
||||||
// }
|
|
||||||
|
|
||||||
func mapToXML(m map[string]interface{}) ([]byte, error) {
|
|
||||||
xmlData := make([]xmlNode, 0)
|
|
||||||
|
|
||||||
for k, v := range m {
|
|
||||||
node := xmlNode{
|
|
||||||
XMLName: xml.Name{Local: k},
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value := v.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
childXML, err := mapToXML(value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
node.Data = childXML
|
|
||||||
default:
|
|
||||||
node.Data = []byte(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlData = append(xmlData, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
return xml.MarshalIndent(xmlData, "", " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
type xmlNode struct {
|
|
||||||
XMLName xml.Name
|
|
||||||
Data []byte `xml:",innerxml"`
|
|
||||||
}
|
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
// Package simpleRequest -----------------------------
|
|
||||||
// @file : utils_test.go
|
|
||||||
// @author : JJXu
|
|
||||||
// @contact : wavingbear@163.com
|
|
||||||
// @time : 2023/11/17 16:37
|
|
||||||
// -------------------------------------------
|
|
||||||
package simpleRequest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_mapToXML(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
m map[string]interface{}
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "多级xml测试",
|
|
||||||
args: args{
|
|
||||||
m: map[string]interface{}{
|
|
||||||
"UserInfo": map[string]any{
|
|
||||||
"Name": "JJXu",
|
|
||||||
"Age": 18,
|
|
||||||
"isTrueMan": true,
|
|
||||||
"assets": map[string]any{
|
|
||||||
"car": "BMW",
|
|
||||||
"house": "shanghai",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: "<UserInfo>\n<Age>18</Age>\n<isTrueMan>true</isTrueMan>\n<assets></assets>\n<Name>JJXu</Name>\n</UserInfo>",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "错误格式测试",
|
|
||||||
args: args{},
|
|
||||||
want: "",
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := mapToXML(tt.args.m)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("mapToXML() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if string(got) != tt.want {
|
|
||||||
t.Errorf("mapToXML() got = %v, want %v", string(got), tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func Test_mapToXML2(t *testing.T) {
|
|
||||||
person := map[string]interface{}{
|
|
||||||
"userInfo": map[string]interface{}{
|
|
||||||
"name": "John",
|
|
||||||
"age": 30,
|
|
||||||
"address": map[string]interface{}{
|
|
||||||
"street": "123 Main St",
|
|
||||||
"city": "New York",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlBytes, err := mapToXML(person)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlString := string(xmlBytes)
|
|
||||||
fmt.Println(xmlString)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user