0

0

Go语言中实现JSON键名不对称映射的自定义Marshaler

心靈之曲

心靈之曲

发布时间:2025-11-30 14:41:12

|

767人浏览过

|

来源于php中文网

原创

Go语言中实现JSON键名不对称映射的自定义Marshaler

本教程探讨了在go语言中,当默认的json:"tag"无法满足json键名在序列化(marshal)和反序列化(unmarshal)时需要不同映射规则的需求。通过实现自定义的marshaljson方法,我们可以精确控制结构体字段如何被序列化为json,从而实现灵活的键名转换,例如将输入json中的"name"字段反序列化到结构体的url字段,并在序列化时将其输出为"url"。

1. Go语言JSON标签的局限性

Go语言的encoding/json包提供了强大且便捷的JSON序列化(Marshal)和反序列化(Unmarshal)功能。通过在结构体字段上使用json:"keyname"标签,开发者可以轻松地将Go结构体与JSON对象进行映射。例如:

type User struct {
    Name string `json:"user_name"`
    Age  int    `json:"user_age"`
}

在上述示例中,当对User结构体进行反序列化时,JSON中的"user_name"键会被映射到Name字段;当进行序列化时,Name字段的值会以"user_name"为键输出到JSON。

然而,json:"keyname"标签存在一个局限性:它为字段指定了一个单一的JSON键名,这个键名在反序列化和序列化过程中都是一致的。这意味着,如果我们的需求是:

  1. 从JSON输入中读取"name"键,并将其值赋给结构体的Url字段。
  2. 在将该结构体序列化回JSON时,将Url字段的值以"url"为键输出。

这种不对称的键名映射(输入"name",输出"url")是无法通过单一json:"tag"直接实现的。

立即学习go语言免费学习笔记(深入)”;

2. 解决方案:实现 json.Marshaler 接口

为了解决上述不对称键名映射的问题,Go语言提供了json.Marshaler接口。该接口定义了一个方法:

type Marshaler interface {
    MarshalJSON() ([]byte, error)
}

当一个类型实现了MarshalJSON()方法时,json.Marshal()函数在序列化该类型的实例时,会优先调用这个自定义方法,而不是使用默认的反射机制。这赋予了我们对序列化过程的完全控制权,可以根据业务逻辑自由地构建JSON输出。

3. 示例:实现不对称键名映射

我们将通过一个具体的例子来演示如何实现json.Marshaler接口,以达到输入"name"键、输出"url"键的目的。

Convai Technologies Inc.
Convai Technologies Inc.

对话式 AI API,用于设计游戏和支持端到端的语音交互

下载

3.1 定义结构体

首先,我们定义一个Data结构体。为了处理反序列化时将JSON中的"name"键映射到Url字段,我们仍然使用json:"name"标签。

type Data struct {
    Url string `json:"name"` // 用于反序列化:将JSON中的"name"映射到Url字段
}

需要注意的是,这里的json:"name"标签只在json.Unmarshal时生效。当调用json.Marshal时,如果Data类型实现了MarshalJSON方法,则该方法会覆盖默认的标签行为。

3.2 辅助函数:构建JSON对象

为了更方便地在MarshalJSON方法中构建JSON对象,我们可以编写一个辅助函数marshalObject。这个函数接收键名切片和值切片,然后将它们组合成一个JSON对象字符串。

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

// marshalObject 接收键名切片和值切片,将它们序列化为一个JSON对象字符串。
// 键名应为合法的JSON字符串(无需额外的双引号包裹)。
func marshalObject(keys []string, values []interface{}) ([]byte, error) {
    if len(keys) != len(values) {
        panic("Different length of keys and values slices")
    }

    if len(keys) == 0 {
        return []byte(`{}`), nil
    }

    var b bytes.Buffer
    b.Write([]byte(`{"`)) // JSON对象开始

    for i, key := range keys {
        if i != 0 {
            b.Write([]byte(`,"`)) // 添加逗号分隔键值对
        }
        b.WriteString(key) // 写入键名
        b.Write([]byte(`":`)) // 写入键值分隔符

        // 递归地对值进行JSON序列化
        j, err := json.Marshal(values[i])
        if err != nil {
            return nil, err
        }
        b.Write(j) // 写入序列化后的值
    }

    b.Write([]byte(`}`)) // JSON对象结束
    return b.Bytes(), nil
}

注意事项: marshalObject函数通过手动拼接字节来构建JSON。它假设传入的keys已经是合法的JSON键字符串(例如"url"而不是url)。对于动态生成的键名,需要确保它们被正确地转义。

3.3 实现 MarshalJSON 方法

现在,我们为Data类型实现MarshalJSON方法。在这个方法中,我们将调用marshalObject,指定Url字段在序列化时应以"url"为键输出。

func (d *Data) MarshalJSON() ([]byte, error) {
    // 在这里定义序列化时使用的键名和对应的值。
    // 我们将 d.Url 字段以 "url" 为键进行序列化。
    return marshalObject(
        []string{
            `url`, // 序列化时将 d.Url 字段输出为 "url" 键
        },
        []interface{}{
            d.Url, // 对应的值是结构体的 Url 字段
        },
    )
}

3.4 完整示例代码

将所有组件整合到一个main.go文件中,进行测试。

package main

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

// Data 结构体定义,使用 `json:"name"` 标签用于反序列化
type Data struct {
    Url string `json:"name"`
}

// marshalObject 辅助函数,用于构建JSON对象
func marshalObject(keys []string, values []interface{}) ([]byte, error) {
    if len(keys) != len(values) {
        panic("Different length of keys and values slices")
    }
    if len(keys) == 0 {
        return []byte(`{}`), nil
    }

    var b bytes.Buffer
    b.Write([]

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

411

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

532

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

617

2023.11.24

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

4

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号