How to Flatten Marshaled JSON Structs with Anonymous Members in Go?

Barbara Streisand
Release: 2024-10-29 07:35:31
Original
215 people have browsed it

How to Flatten Marshaled JSON Structs with Anonymous Members in Go?

Flattening Marshaled JSON Structs with Anonymous Members in Go

When marshaling JSON data in Go, anonymous members can introduce unexpected complexities. This article delves into a solution that addresses these challenges.

The Issue

Consider the following code:

<code class="go">type Hateoas struct {
    Anything
    Links map[string]string `json:"_links"`
}</code>
Copy after login

When Hateoas contains anonymous members, the JSON marshaler treats them as regular named fields, resulting in undesired nesting:

<code class="json">{
    "Anything": {
        "id": 123,
        "name": "James Dean"
    },
    "_links": {
        "self": "http://user/123"
    }
}</code>
Copy after login

Solution: Reflection-Based Flattening

To flatten the JSON structure and eliminate the extra nesting, we can utilize reflection:

<code class="go">subjectValue := reflect.Indirect(reflect.ValueOf(subject))
subjectType := subjectValue.Type()
for i := 0; i < subjectType.NumField(); i++ {
    field := subjectType.Field(i)
    name := subjectType.Field(i).Name
    out[field.Tag.Get("json")] = subjectValue.FieldByName(name).Interface()
}</code>
Copy after login

This loop iterates over the fields of the struct, extracts their JSON tag names, and maps them to a flattened map[string]interface{}. By using reflection, we avoid adding new named fields and retain the original flat structure.

Example

Here's an example of how to use this solution:

<code class="go">import "reflect"

func MarshalHateoas(subject interface{}) ([]byte, error) {
    links := make(map[string]string)
    out := make(map[string]interface{})
    subjectValue := reflect.Indirect(reflect.ValueOf(subject))
    subjectType := subjectValue.Type()
    for i := 0; i < subjectType.NumField(); i++ {
        field := subjectType.Field(i)
        name := subjectType.Field(i).Name
        out[field.Tag.Get("json")] = subjectValue.FieldByName(name).Interface()
    }
    switch s := subject.(type) {
    case *User:
        links["self"] = fmt.Sprintf("http://user/%d", s.Id)
    case *Session:
        links["self"] = fmt.Sprintf("http://session/%d", s.Id)
    }
    out["_links"] = links
    return json.MarshalIndent(out, "", "    ")
}</code>
Copy after login

With this improved MarshalHateoas function, the sample JSON output becomes:

<code class="json">{
    "id": 123,
    "name": "James Dean",
    "_links": {
        "self": "http://user/123"
    }
}</code>
Copy after login

Conclusion

By leveraging reflection, we can effectively flatten JSON structs with anonymous members and achieve the desired JSON structure without compromising data integrity. This solution provides a robust way to handle complex JSON serialization scenarios in Go.

The above is the detailed content of How to Flatten Marshaled JSON Structs with Anonymous Members in Go?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template