Golang实现JSON与SOAP数据转换的方法探讨

Golang实现JSON与SOAP数据转换的方法探讨 你好!

在我目前公司的岗位上,我们使用 DataWeave 来将请求从 JSON(或 Java 对象)转换为 SOAP 格式,反之亦然,因为我们与支持 SOAP 的服务进行交互,包括有上下文和无上下文的调用。

我想知道发送 JSON 数据并将其转换为 SOAP 请求有多困难。我的理解是,一个潜在的 JSON 对象是否必须首先被解组(unmarshal)为一个 Go 结构体,然后再转换为 SOAP 请求?这个假设正确吗?

关于同一个话题,使用一个库或者为 Go 结构体创建一个自定义的 WSDL 转换器有多难?我知道有一些现成的库,但我不确定是否有推荐的库?


更多关于Golang实现JSON与SOAP数据转换的方法探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

太棒了,谢谢!

更多关于Golang实现JSON与SOAP数据转换的方法探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


与任何API转换一样,你需要通过某种内部表示将源请求转换为目标请求中的内容。

即使是简单的REST到REST转换也是如此。

你无法将“JSON”转换为“SOAP”,因为“JSON”是一种结构化数据(即有效载荷)的方式,而SOAP是一种API规范,它不仅规定了有效载荷的格式(必须是XML),还规定了请求的布局方式。

总之,是的,你需要一个请求的内部表示,以便能够进行转换。

至于你是使用结构体还是其他方式来表示它,这取决于你。

在Go中实现JSON与SOAP转换确实需要中间的结构体转换。你的理解基本正确,但具体实现可以有多种方式。

基本转换流程

package main

import (
    "encoding/json"
    "encoding/xml"
    "fmt"
)

// SOAP结构体定义
type SOAPEnvelope struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
    Body    SOAPBody `xml:"Body"`
}

type SOAPBody struct {
    XMLName xml.Name `xml:"Body"`
    Data    interface{}
}

// 业务数据结构
type UserRequest struct {
    XMLName xml.Name `xml:"UserRequest"`
    ID      int      `xml:"id" json:"id"`
    Name    string   `xml:"name" json:"name"`
    Email   string   `xml:"email" json:"email"`
}

// JSON转SOAP
func JSONToSOAP(jsonData []byte) ([]byte, error) {
    var user UserRequest
    
    // 1. JSON解组到结构体
    if err := json.Unmarshal(jsonData, &user); err != nil {
        return nil, err
    }
    
    // 2. 构建SOAP信封
    envelope := SOAPEnvelope{
        Body: SOAPBody{
            Data: user,
        },
    }
    
    // 3. 生成SOAP XML
    soapXML, err := xml.MarshalIndent(envelope, "", "  ")
    if err != nil {
        return nil, err
    }
    
    // 添加XML头部
    result := []byte(xml.Header + string(soapXML))
    return result, nil
}

// SOAP转JSON
func SOAPToJSON(soapData []byte) ([]byte, error) {
    var envelope SOAPEnvelope
    envelope.Body.Data = &UserRequest{}
    
    // 1. XML解组到SOAP结构体
    if err := xml.Unmarshal(soapData, &envelope); err != nil {
        return nil, err
    }
    
    // 2. 转换为JSON
    jsonData, err := json.MarshalIndent(envelope.Body.Data, "", "  ")
    if err != nil {
        return nil, err
    }
    
    return jsonData, nil
}

func main() {
    // 示例JSON数据
    jsonInput := `{"id": 123, "name": "张三", "email": "zhangsan@example.com"}`
    
    // JSON转SOAP
    soap, err := JSONToSOAP([]byte(jsonInput))
    if err != nil {
        panic(err)
    }
    fmt.Println("SOAP输出:")
    fmt.Println(string(soap))
    
    // SOAP转JSON
    jsonOutput, err := SOAPToJSON(soap)
    if err != nil {
        panic(err)
    }
    fmt.Println("\nJSON输出:")
    fmt.Println(string(jsonOutput))
}

推荐的SOAP库

对于生产环境,建议使用成熟的SOAP库:

1. github.com/hooklift/gowsdl

package main

import (
    "fmt"
    "github.com/hooklift/gowsdl/soap"
)

// 生成客户端代码
// go:generate gowsdl -o service.go -p main https://example.com/service?wsdl

func main() {
    client := soap.NewClient("https://example.com/service")
    
    // 使用生成的客户端代码调用SOAP服务
    // response, err := client.SomeOperation(&request)
}

2. github.com/tiaguinho/gosoap

package main

import (
    "fmt"
    "github.com/tiaguinho/gosoap"
)

func main() {
    // 创建SOAP客户端
    client, err := gosoap.SoapClient("http://example.com/soap")
    if err != nil {
        panic(err)
    }
    
    // 设置SOAP请求参数
    params := gosoap.Params{
        "id":    123,
        "name":  "张三",
        "email": "zhangsan@example.com",
    }
    
    // 调用SOAP方法
    response, err := client.Call("UserOperation", params)
    if err != nil {
        panic(err)
    }
    
    // 获取响应
    result := response.Get("UserResponse")
    fmt.Println(result)
}

3. 自定义WSDL转换器示例

package main

import (
    "encoding/xml"
    "strings"
)

type WSDLConverter struct {
    Namespace string
    Service   string
}

func (w *WSDLConverter) GenerateSOAPRequest(method string, data interface{}) (string, error) {
    // 构建SOAP请求模板
    template := `<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:ns="%s">
    <soap:Body>
        <ns:%s>
            %s
        </ns:%s>
    </soap:Body>
</soap:Envelope>`
    
    // 将数据转换为XML
    xmlData, err := xml.Marshal(data)
    if err != nil {
        return "", err
    }
    
    // 移除XML头部
    xmlStr := strings.TrimSpace(string(xmlData))
    xmlStr = strings.Replace(xmlStr, `<?xml version="1.0" encoding="UTF-8"?>`, "", 1)
    
    request := fmt.Sprintf(template, w.Namespace, method, xmlStr, method)
    return request, nil
}

// 使用示例
func main() {
    converter := &WSDLConverter{
        Namespace: "http://example.com/ns",
        Service:   "UserService",
    }
    
    user := UserRequest{
        ID:    123,
        Name:  "张三",
        Email: "zhangsan@example.com",
    }
    
    soapRequest, err := converter.GenerateSOAPRequest("CreateUser", user)
    if err != nil {
        panic(err)
    }
    
    fmt.Println(soapRequest)
}

处理复杂SOAP特性

package main

import (
    "encoding/xml"
    "fmt"
)

// 处理SOAP头部
type SOAPHeader struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"`
    Auth    *AuthHeader
}

type AuthHeader struct {
    XMLName  xml.Name `xml:"auth"`
    Username string   `xml:"username"`
    Password string   `xml:"password"`
}

// 完整的SOAP请求
type FullSOAPEnvelope struct {
    XMLName xml.Name   `xml:"soap:Envelope"`
    XMLNS   string     `xml:"xmlns:soap,attr"`
    Header  *SOAPHeader `xml:"soap:Header,omitempty"`
    Body    SOAPBody   `xml:"soap:Body"`
}

// 生成带认证的SOAP请求
func CreateAuthenticatedSOAPRequest(bodyData interface{}) ([]byte, error) {
    envelope := FullSOAPEnvelope{
        XMLNS: "http://schemas.xmlsoap.org/soap/envelope/",
        Header: &SOAPHeader{
            Auth: &AuthHeader{
                Username: "admin",
                Password: "secret",
            },
        },
        Body: SOAPBody{
            Data: bodyData,
        },
    }
    
    return xml.MarshalIndent(envelope, "", "  ")
}

这些示例展示了在Go中处理JSON与SOAP转换的基本模式。对于生产环境,建议使用成熟的SOAP库,它们已经处理了SOAP协议的各种细节,如命名空间、SOAP错误处理、WS-Security等。

回到顶部