【问题标题】:Convert from and to messagepack从消息包转换为消息包
【发布时间】:2018-11-29 20:21:52
【问题描述】:

所以我试图在 Golang 中获取 JSON 消息的字符串表示。我只是想接收消息包编码的 JSON,修改一些值并将其发送回来。

我还没有找到一个简单的方法来做到这一点。大多数时候,我无法提前知道 JSON 的结构是什么(除了 JSON 结构之外),所以我想做的就是接收二进制消息。将其解码为 JSON,将其作为字符串打印到标准输出,修改内容,再次将其转换为 MessagePack 并发送回。

我一直在看这两个包,但我不知道如何正确地使用它们来完成这样的简单任务:

所以我会收到这样的东西:

DF 00 00 00 01 A7 6D 65 73 73 61 67 65 A3 48 69 21

我想打印这个:

{"message": "Hi!"}

修改“嗨!”:

{"message": "Hello Sir!"}

作为消息包发送:

DF 00 00 00 01 A7 6D 65 73 73 61 67 65 AA 48 65 6C 6C 6F 20 53 69 72 21

我正在尝试移植到 Golang 的当前 Python 代码:

def decode_msgpack(jsonData):
    packedStuff = 0
    for key in jsonData.keys():
        if type(jsonData[key]) is bytes:
            packedStuff += 1
            try:
                jsonData[key] = umsgpack.unpackb(jsonData[key])
            except umsgpack.InvalidStringException:
                try:
                    jsonData[key] = umsgpack.unpackb(jsonData[key], allow_invalid_utf8=True)
                except umsgpack.InsufficientDataException:
                    print("[!] InsufficientDataException")
                    jsonData[key] = base64.b64encode(jsonData[key]).decode('utf-8')
                else:
                    jsonData[key] = base64.b64encode(jsonData[key]).decode('utf-8')

    if packedStuff > 0:
        return decode_msgpack(jsonData)
    else:
        return jsonData

【问题讨论】:

    标签: go msgpack


    【解决方案1】:

    使用编解码器库并假设{"message": "Hi"} 是一个映射,代码看起来像这样。

    package main
    
    import (
            "fmt"
    
            "github.com/ugorji/go/codec"
    )
    
    func main() {
            var data []byte
            original := map[string]string{"message": "Hi!"}
            enc := codec.NewEncoderBytes(&data, new(codec.MsgpackHandle))
            if err := enc.Encode(&original); err != nil {
                    panic(err)
            }
            fmt.Printf("Encoded: ")
            for _, b := range data {
                    fmt.Printf("%X ", b)
            }
            fmt.Printf("\n")
            decoded := make(map[string]string)
            dec := codec.NewDecoderBytes(data, new(codec.MsgpackHandle))
            if err := dec.Decode(&decoded); err != nil {
                    panic(err)
            }
            fmt.Printf("Decoded: %v\n", decoded)
            decoded["message"] = "Hello Sir!"
            /* reinitialize the encoder */
            enc = codec.NewEncoderBytes(&data, new(codec.MsgpackHandle))
            if err := enc.Encode(&decoded); err != nil {
                    panic(err)
            }
            fmt.Printf("Encoded: ")
            for _, b := range data {
                    fmt.Printf("%X ", b)
            }
            fmt.Printf("\n")
    }
    

    也就是说,如果您将{"message": "Hi"} 作为 JSON 字符串,您可以使用编解码器将 JSON 解码为地图,更新地图,然后将其重新编码为 msgpack。

    【讨论】:

    • 感谢疯狂袋熊的回答!这看起来像我需要的,但是当我得到这样的东西时我遇到了问题:{"user": "nobody", "message": {"number": 003, "content": "Hi!"}} 检查我的原始问题,了解我在 Python3 上的操作方式
    • 如果您知道 JSON 结构将是什么,最好的办法是定义具有正确字段的自定义结构类型,然后将其与编解码器而不是映射一起使用来编码/解码/更新东西。
    • 我要更新代码来做自定义类型而不是地图
    • 问题是我不知道所有可能的不同类型的消息。我会在未来,但现在这不是一个选择。
    • 如果您不知道消息中包含哪些字段,您将如何更新消息?
    【解决方案2】:

    最好的方法是先解码,通过 Go 结构进行更改,然后重新编码。

    data := []byte(`{"message": "Hi!"}`)
    var p map[string]interface{}
    
    // Decode into Struct
    if err := json.Unmarshal(data, &p); err != nil {
        // TODO: handle err
    }
    
    // Modify contents
    p["message"] = "Hello Sir!"
    
    // Encode from struct
    newData, err := json.Marshal(p)
    if err != nil {
        // TODO: Handle err
    }
    
    fmt.Println(string(newData))
    

    【讨论】:

    • 这个方案,据我了解,要求我事先知道JSON的格式,还是我错了?因为根据您的示例,“有效负载”必须是具有适当字段的结构以容纳解码的消息。也许我误解了它:P
    • 我想这取决于您对格式的了解程度。我会用一些更动态的东西来更新我的答案,看看是否有帮助。
    • 我唯一知道的是遵循 JSON RFC (tools.ietf.org/html/rfc8259),并且根据消息包规范,如果你有类似的东西:{"user": "nobody", "message": {"type": "init", "content":"Hi Sir!"}} 首先内部对象被转换为它的消息包表示形式字节,然后是整个 JSON。
    猜你喜欢
    • 2011-03-06
    • 2011-07-07
    • 2018-09-05
    • 2015-07-27
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 2020-10-02
    • 1970-01-01
    相关资源
    最近更新 更多