gpt4 book ai didi

JSON Marshal uint 或 int 作为整数

转载 作者:数据小太阳 更新时间:2023-10-29 03:36:57 24 4
gpt4 key购买 nike

我正在寻找有关 json marshal with Go 的信息。我先说明一下情况。

我正在为 IoT 设备开发应用程序。该应用程序将 MQTT 数据包中的 JSON 发送给我们的代理。设备如何使用 SIM 卡进行数据连接我需要将数据包的字节数减少到最少。

现在,JSON 具有这种结构

{
"d": 1524036831
"p": "important message"
}

d 字段是时间戳,p 是有效负载。

当应用发送此 JSON 时,它有 40 个字节。但是如果 d 是 1000,pe,JSON 将是 34 字节。所以 marshal 将字段 d 转换为 uint32 到数字的 ASCII 表示,然后发送字符串。

我想要的是将此字段作为 true int 或 uint 发送。我想说,1524036831是一个int32,4个字节,和1000一样。因此,通过此更改,我可以将数据包大小减少一些字节,并且该数字能够增长到 32 位。

我阅读了 json.Marshal 的文档,但没有找到任何相关信息。

我找到了一个“解决方案”,但我认为它不是很漂亮,但可以解决问题。我想要其他意见。

丑陋的解决方案(对我来说)

package main

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

type test struct {
Data uint32 `json:"d"`
Payload string `json:"p"`
}
type testB struct {
Data []byte `json:"d"`
Payload string `json:"p"`
}

func main() {
fmt.Println("TEST with uin32")
d := []test{test{Data: 5, Payload: "Important Message"}, test{Data: 10, Payload: "Important Message"}, test{Data: 1000, Payload: "Important Message"}, test{Data: 1524036831, Payload: "Important Message"}}
for _, i := range d {
j, _ := json.Marshal(i)
fmt.Println(string(j))
fmt.Println("All:", len(j))
fmt.Println("-----------")
}
fmt.Println("\nTEST with []Byte")
d1 := []testB{testB{Data: make([]byte, 4), Payload: "Important Message"}, testB{Data: make([]byte, 4), Payload: "Important Message"}, testB{Data: make([]byte, 4), Payload: "Important Message"}, testB{Data: make([]byte, 4), Payload: "Important Message"}}
binary.BigEndian.PutUint32(d1[0].Data, 5)
binary.BigEndian.PutUint32(d1[1].Data, 20)
binary.BigEndian.PutUint32(d1[2].Data, 1000)
binary.BigEndian.PutUint32(d1[3].Data, 1524036831)
for _, i := range d1 {
j, _ := json.Marshal(i)
fmt.Println(string(j))
fmt.Println(len(j))
fmt.Println("-----------")
}
}

Play

最佳答案

重申一下我的评论:JSON 是一种文本格式,而文本格式并不是为了生成小消息而设计的。特别是在 JSON 中除了十进制字符串之外没有数字表示。

以大于 10 的基数编码数字将减少足够大数字的消息大小。

您可以通过删除前导零字节并使用 base64.RawStdEncoding(省略填充字符)进行编码来减少“丑陋”代码生成的消息大小。这样做对数字 >= 1e6 是有好处的。

如果你把这一切都放在一个自定义类型中,它会变得更好用:

package main

import (
"bytes"
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
)

type IntB64 uint32

func (n IntB64) MarshalJSON() ([]byte, error) {
b := make([]byte, 4)

binary.BigEndian.PutUint32(b, uint32(n))
b = bytes.TrimLeft(b, string(0))

// All characters in the base64 alphabet need not be escaped, so we don't
// have to call json.Marshal here.
l := base64.RawStdEncoding.EncodedLen(len(b)) + 2
j := make([]byte, l)

base64.RawStdEncoding.Encode(j[1:], b)
j[0], j[l-1] = '"', '"'

return j, nil
}

func main() {
enc(1) // "AQ"
enc(1000) // "A+g"
enc(1e6 - 1) // "D0I/"
enc(1e6) // "D0JA"
enc(1524036831) // "Wtb03w"
}

func enc(n int64) {
b, _ := json.Marshal(IntB64(n))
fmt.Printf("%10d %s\n", n, string(b))
}

更新 Playground :https://play.golang.org/p/7Z03VE9roqN

关于JSON Marshal uint 或 int 作为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49896677/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com