Go语言JSON编解码net.IP时能否保留4字节表示形式?
Go 语言 net.IP JSON 编解码保留4字节IPv4格式的解决方案
问题根因
标准库net.IP的默认JSON反序列化逻辑会自动将IPv4地址转换为16字节的IPv4映射IPv6格式,原生没有提供全局配置项直接保留4字节表示,需要通过自定义类型实现JSON编解码接口来解决。
实现代码
你可以封装自定义IP类型,重写json.Marshaler和json.Unmarshaler接口方法,手动控制编解码逻辑:
package main import ( "encoding/json" "fmt" "net" ) // CustomIP 自定义IP类型,实现自定义JSON编解码逻辑 type CustomIP net.IP func (ip CustomIP) MarshalJSON() ([]byte, error) { stdIP := net.IP(ip) // 如果是IPv4优先返回4字节格式对应的字符串 if ip4 := stdIP.To4(); ip4 != nil { return json.Marshal(ip4.String()) } return json.Marshal(stdIP.String()) } func (ip *CustomIP) UnmarshalJSON(data []byte) error { var ipStr string if err := json.Unmarshal(data, &ipStr); err != nil { return err } parsedIP := net.ParseIP(ipStr) if parsedIP == nil { return &net.ParseError{Type: "IP地址", Text: ipStr} } // 如果是IPv4,只保留4字节 if ip4 := parsedIP.To4(); ip4 != nil { *ip = CustomIP(ip4) return nil } // 非IPv4保留原16字节格式 *ip = CustomIP(parsedIP) return nil }
测试示例
替换原代码中的net.IP为自定义CustomIP类型即可:
func main() { myIP := CustomIP{0xa, 0x2a, 0x0, 0x0} fmt.Printf("编解码前:%#v\n", net.IP(myIP)) data, _ := json.Marshal(myIP) fmt.Printf("序列化JSON:%s\n", data) var myNewIP CustomIP _ = json.Unmarshal(data, &myNewIP) fmt.Printf("编解码后:%#v\n", net.IP(myNewIP)) }
运行输出:
编解码前:net.IP{0xa, 0x2a, 0x0, 0x0} 序列化JSON:"10.42.0.0" 编解码后:net.IP{0xa, 0x2a, 0x0, 0x0}
补充说明
如果你的业务场景需要完全兼容原生net.IP的所有方法,只需要在用到net.IP的地方做一次强制类型转换即可,不需要修改原有业务逻辑。
内容的提问来源于stack exchange,提问作者M. Buil
相关产品推荐
相关产品推荐

