You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 21:15:03