目录
问题内容
解决方法
首页 后端开发 Golang 在golang中从struct手动创建json对象

在golang中从struct手动创建json对象

Feb 12, 2024 am 11:03 AM
overflow

在golang中从struct手动创建json对象

在golang中,从struct手动创建json对象是一项常见的操作。通过将struct转换为json格式,我们可以方便地在网络传输或存储中使用。在本文中,php小编香蕉将向您介绍如何使用golang的内置包来实现这一功能。不仅如此,我们还将探讨如何处理struct中的嵌套字段以及如何处理特殊类型的字段。无论您是初学者还是有经验的开发者,本文都将为您提供详细的指导,帮助您轻松地在golang中创建json对象。让我们开始吧!

问题内容

我有一个结构可以说

<code>type Foo struct {
  A string `json:",omitemtpy"
}
</code>
登录后复制

我知道我可以使用类似的东西轻松地将其转换为 json

json.Marshal(Foo{})
登录后复制

它将返回一个空的 json 字符串。

但我需要使用相同的结构返回结构的 json 表示形式,其中包含所有字段和 json 中存在的“空值”。 (实际上,它是一个非常大的结构,所以我不能只保留没有标签的副本)

最简单的方法是什么?

基本上,我需要创建一个忽略 json omitempty 标签的结构的 json 编组。

此 json 创建不需要高效或高性能。

我更希望有一个库可以用于此类任务,但我见过的大多数库要么创建一些特殊格式,要么尊重 omitempty

编辑:

选择 https://stackoverflow.com/a/77799949/2187510 作为我的答案,并进行一些额外的工作以允许默认值(使用其代码作为参考)

defaultFoo := FoodWithPts{ Str: "helloWorld"}
dupFooType := dupType(reflect.TypeOf(defaultFoo))
foo := reflect.Zero(dupFooType).Interface()

// New additions
defaults, _ := json.Marshal(defaultFoo)
json.Unmarshal(defaults, &foo)   // overwrites foo with defaults
// End New additions

data, err := json.Marshal(foo)
fmt.Println("dup FooWithPtrs:\n", string(data), err)
登录后复制

输出:

dup FooWithPtrs:
    {"String":"helloWorld","Int":0,"Bar":null} <nil>
登录后复制

解决方法

您无法在运行时修改标签,但可以使用 $$c 在运行时创建结构类型$$reflect.StructOf()

因此,我们的想法是复制结构类型,但在重复中从 JSON 标记中排除 ,omitempty<code>,omitempty 选项。

您可以在 Go Playground 上找到以下所有示例。

这比人们一开始想象的要容易。我们只需要递归地执行(一个结构体字段可能是另一个结构体),并且我们绝对应该处理指针:

func dupType(t reflect.Type) reflect.Type {
    if t.Kind() == reflect.Pointer {
        return reflect.PointerTo(dupType(t.Elem()))
    }

    if t.Kind() != reflect.Struct {
        return t
    }

    var fields []reflect.StructField

    for i := 0; i < t.NumField(); i++ {
        sf := t.Field(i)
        sf.Type = dupType(sf.Type)
        // Keep json tag but cut ,omitempty option if exists:
        if tag, _ := strings.CutSuffix(sf.Tag.Get("json"), ",omitempty"); tag == "" {
            sf.Tag = ""
        } else {
            sf.Tag = `json:"` + reflect.StructTag(tag) + `"`
        }
        fields = append(fields, sf)
    }

    return reflect.StructOf(fields)
}
登录后复制

让我们用这种类型来测试它:

type Foo struct {
    Str string `json:"String,omitempty"`
    Int int    `json:",omitempty"`
    Bar struct {
        Float  float64 `json:",omitempty"`
        PtrInt int     `json:",omitempty"`
        Baz    struct {
            X int `json:"XXXX,omitempty"`
        } `json:",omitempty"`
    } `json:",omitempty"`
}
登录后复制

首先,这是没有类型重复的 JSON 输出:

data, err := json.Marshal(Foo{})
fmt.Println("Foo:\n", string(data), err)
登录后复制

输出:

Foo:
 {"Bar":{"Baz":{}}} <nil>
登录后复制

请注意,我们得到了 Bar<code>BarBazBaz</p> 字段,因为它们是结构体。<p> </p>让我们尝试类型复制:<p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>dupFooType := dupType(reflect.TypeOf(Foo{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println(&quot;dup Foo:\n&quot;, string(data), err)</pre><div class="contentsignin">登录后复制</div></div> </p>这将输出:<p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>dup Foo: {&quot;String&quot;:&quot;&quot;,&quot;Int&quot;:0,&quot;Bar&quot;:{&quot;Float&quot;:0,&quot;PtrInt&quot;:0,&quot;Baz&quot;:{&quot;XXXX&quot;:0}}} &lt;nil&gt;</pre><div class="contentsignin">登录后复制</div></div> </p>不错!正是我们想要的!<p> </p>但我们还没有完成。如果我们有一个带有结构指针字段的类型怎么办?像这样:<p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>type FooWithPtrs struct { Str string `json:&quot;String,omitempty&quot;` Int int `json:&quot;,omitempty&quot;` Bar *struct { Float float64 `json:&quot;,omitempty&quot;` PtrInt int `json:&quot;,omitempty&quot;` Baz *struct { X int `json:&quot;XXXX,omitempty&quot;` } `json:&quot;,omitempty&quot;` } `json:&quot;,omitempty&quot;` }</pre><div class="contentsignin">登录后复制</div></div> </p>尝试对重复类型的值进行 JSON 编组:<p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>dupFooType := dupType(reflect.TypeOf(FooWithPtrs{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println(&quot;dup FooWithPtrs:\n&quot;, string(data), err)</pre><div class="contentsignin">登录后复制</div></div> </p>输出:<p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>dup FooWithPtrs: {&quot;String&quot;:&quot;&quot;,&quot;Int&quot;:0,&quot;Bar&quot;:null} &lt;nil&gt;</pre><div class="contentsignin">登录后复制</div></div> <code>null,但我们也希望它们的字段也出现在输出中。这需要将它们初始化为非 nil如果结构包含指针,则这些指针在 JSON 输出中显示为 null

,但我们也希望它们的字段也出现在输出中。这需要将它们初始化为非 nil

值,以便它们生成输出。

幸运的是,我们还可以使用反射来做到这一点:

func initPtrs(v reflect.Value) {
    if !v.CanAddr() {
        return
    }

    if v.Kind() == reflect.Pointer {
        v.Set(reflect.New(v.Type().Elem()))
        v = v.Elem()
    }

    if v.Kind() == reflect.Struct {
        for i := 0; i < v.NumField(); i++ {
            initPtrs(v.Field(i))
        }
    }
}
登录后复制

我们很兴奋!让我们看看实际效果:

dupFooType := dupType(reflect.TypeOf(FooWithPtrs{}))
fooVal := reflect.New(dupFooType)
initPtrs(fooVal.Elem())

data, err := json.Marshal(fooVal.Interface())
fmt.Println("dup and inited FooWithPtrs:\n", string(data), err)
登录后复制

输出:

dup and inited FooWithPtrs:
 {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
登录后复制
🎜不错!它包含所有字段!🎜

以上是在golang中从struct手动创建json对象的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

比特币诞生至今价格2009-2025 最全的BTC历史价格汇总 比特币诞生至今价格2009-2025 最全的BTC历史价格汇总 Jan 15, 2025 pm 08:11 PM

自 2009 年问世以来,比特币成为加密货币界的领头羊,其价格经历了巨大的波动。为了提供全面的历史概述,本文汇集了从 2009 年到 2025 年的比特币价格数据,涵盖了重大的市场事件、市场情绪变化和影响价格走势的重要因素。

比特币诞生至今历史价格总览 比特币历史价格趋势大全 比特币诞生至今历史价格总览 比特币历史价格趋势大全 Jan 15, 2025 pm 08:14 PM

比特币,作为一种加密货币,自问世以来经历了显着的市场波动。本文将提供比特币自诞生以来的历史价格总览,帮助读者了解其价格趋势和关键时刻。通过分析比特币的历史价格数据,我们可以了解市场对其价值评估、影响其波动的因素,并为未来投资决策提供依据。

比特币诞生至今历史价格一览 BTC历史价格行情趋势图(最新汇总) 比特币诞生至今历史价格一览 BTC历史价格行情趋势图(最新汇总) Feb 11, 2025 pm 11:36 PM

比特币自 2009 年创世以来,价格经历多次大幅波动,最高涨至 2021 年 11 月的 69,044.77 美元,最低跌至 2018 年 12 月的 3,191.22 美元。截至 2024 年 12 月,最新价格突破 100,204 美元。

2018-2024年比特币最新价格美元大全 2018-2024年比特币最新价格美元大全 Feb 15, 2025 pm 07:12 PM

实时比特币美元价格 影响比特币价格的因素 预测比特币未来价格的指标 以下是 2018-2024 年比特币价格的一些关键信息:

如何通过CSS自定义resize符号并使其与背景色统一? 如何通过CSS自定义resize符号并使其与背景色统一? Apr 05, 2025 pm 02:30 PM

CSS自定义resize符号的方法与背景色统一在日常开发中,我们经常会遇到需要自定义用户界面细节的情况,比如调...

H5页面制作是前端开发吗 H5页面制作是前端开发吗 Apr 05, 2025 pm 11:42 PM

是的,H5页面制作是前端开发的重要实现方式,涉及HTML、CSS和JavaScript等核心技术。开发者通过巧妙结合这些技术,例如使用&lt;canvas&gt;标签绘制图形或使用JavaScript控制交互行为,构建出动态且功能强大的H5页面。

如何使用CSS的clip-path属性实现分段器的45度曲线效果? 如何使用CSS的clip-path属性实现分段器的45度曲线效果? Apr 04, 2025 pm 11:45 PM

如何实现分段器的45度曲线效果?在实现分段器的过程中,如何让点击左侧按钮时右侧边框变成45度曲线,而点�...

Flex布局下文字超出省略却撑开容器?如何解决? Flex布局下文字超出省略却撑开容器?如何解决? Apr 05, 2025 pm 11:00 PM

Flex布局下文字超出省略导致容器撑开的问题及解决方法在使用Flex...

See all articles