Manually create json object from struct in golang
In golang, manually creating a json object from a struct is a common operation. By converting struct to json format, we can easily use it in network transmission or storage. In this article, PHP editor Banana will introduce you how to use golang's built-in package to achieve this function. Not only that, we will also explore how to deal with nested fields in structs and how to deal with special types of fields. Whether you are a beginner or an experienced developer, this article will provide you with detailed guidance to help you easily create json objects in golang. let's start!
Question content
I have a structure to say
<code>type Foo struct { A string `json:",omitemtpy" } </code>
I know I can easily convert it to json using something like this
json.Marshal(Foo{})
It will return an empty json string.
But I need to use the same structure to return the json representation of the structure with all the fields and "null values" present in the json. (Actually, it's a very large structure, so I can't just keep a copy without tags)
What's the easiest way?
Basically, I need to create a json marshal of a structure that ignores the json omitempty tag.
This json creation does not need to be efficient or performant.
I would have preferred a library for this kind of task, but most libraries I've seen either create some special format or respect omitempty
edit:
Choose https://stackoverflow.com/a/77799949/2187510 as my answer and do some extra work to allow default values (using its code as a reference)
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)
Output:
dup FooWithPtrs: {"String":"helloWorld","Int":0,"Bar":null} <nil>
Workaround
You cannot modify tags at runtime, but you can use $$c to create struct types at runtime$$reflect.StructOf().
So the idea is to copy the struct type but exclude the ,omitempty
option from the JSON tag in the duplication.
You can find all examples below on Go Playground.
This is easier than people first think. We just need to do it recursively (one struct field might be another struct), and we should definitely deal with pointers:
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) }
Let's test it with this type:
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"` }
First, here is the JSON output without type duplication:
data, err := json.Marshal(Foo{}) fmt.Println("Foo:\n", string(data), err)
Output:
Foo: {"Bar":{"Baz":{}}} <nil>
Note that we get the Bar
and Baz
fields because they are structs.
Let’s try type copy:
dupFooType := dupType(reflect.TypeOf(Foo{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println("dup Foo:\n", string(data), err)
This will output:
dup Foo: {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
good! Exactly what we wanted!
But we're not done yet. What if we have a type with a structure pointer field? like this:
type FooWithPtrs 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"` }
Attempt to JSON marshal values of repeated types:
dupFooType := dupType(reflect.TypeOf(FooWithPtrs{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println("dup FooWithPtrs:\n", string(data), err)
Output:
dup FooWithPtrs: {"String":"","Int":0,"Bar":null} <nil>
If the structure contains pointers, these pointers appear in the JSON output as null
, but we would like their fields to appear in the output as well. This requires them to be initialized to non-nil
values in order for them to produce output.
Fortunately, we can also use reflection to do this:
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)) } } }
We are excited! Let’s see it in action:
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)
Output:
dup and inited FooWithPtrs: {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
good! It contains all fields!
The above is the detailed content of Manually create json object from struct in golang. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Yes, H5 page production is an important implementation method for front-end development, involving core technologies such as HTML, CSS and JavaScript. Developers build dynamic and powerful H5 pages by cleverly combining these technologies, such as using the <canvas> tag to draw graphics or using JavaScript to control interaction behavior.

How to use JavaScript or CSS to control the top and end of the page in the browser's printing settings. In the browser's printing settings, there is an option to control whether the display is...

Regarding the reasons and solutions for misaligned display of inline-block elements. When writing web page layout, we often encounter some seemingly strange display problems. Compare...

How to achieve the 45-degree curve effect of segmenter? In the process of implementing the segmenter, how to make the right border turn into a 45-degree curve when clicking the left button, and the point...

The method of customizing resize symbols in CSS is unified with background colors. In daily development, we often encounter situations where we need to customize user interface details, such as adjusting...

Compatibility issues of multi-row overflow on mobile terminal omitted on different devices When developing mobile applications using Vue 2.0, you often encounter the need to overflow text...

Real-time Bitcoin USD Price Factors that affect Bitcoin price Indicators for predicting future Bitcoin prices Here are some key information about the price of Bitcoin in 2018-2024:

Tips for Implementing Segmenter Effects In user interface design, segmenter is a common navigation element, especially in mobile applications and responsive web pages. ...
