Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Golang / Go – How to marshal struct to null if it has no fields?

I know this would probably seem a common question, but bare with me…

I have a struct with one of the fields type equal to that of another struct:

type Developer struct {
    Name       string `json:"name,omitempty"`
    ProjectRef *Ref   `json:"project,omitempty"`
}

type Ref struct {
    ID string `json:"id,omitempty"`
}

In my implementation I cannot guarantee if there is or isn’t going to be a ProjectRef for a Developer. If I create a Ref with a null ID, i.e. an empty string, then this field is omitted from the Ref, however, even though my Ref has no fields at this point, why is it not omitted from being empty?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I guess one way of overcoming this would be with a bunch of conditional statements, but I don’t want to bring myself to doing that because I have a lot of cases where this functionality is desired.

Full demo code:

package main

import (
    "encoding/json"
    "fmt"
)

type Developer struct {
    Name       string `json:"name,omitempty"`
    ProjectRef *Ref   `json:"project,omitempty"`
}

type Ref struct {
    ID string `json:"id,omitempty"`
}

func main() {
    developer := &Developer{
        Name:       "Charlie",
        ProjectRef: &Ref{ID: ""},
    }

    jsonBytes, err := json.Marshal(developer)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(jsonBytes))
// {"name":"Charlie","project":{}}
}

Link to playground: https://go.dev/play/p/D2edbrACXY2

Thank you in advance

>Solution :

Write a custom JSON marshaler for Ref, which could marshal the JSON null value if the ID is empty:

func (r *Ref) MarshalJSON() ([]byte, error) {
    if r.ID == "" {
        return []byte("null"), nil
    }
    type ref2 Ref
    return json.Marshal((*ref2)(r))
}

Testing it:

developer := &Developer{
    Name:       "Charlie",
    ProjectRef: &Ref{ID: ""},
}

jsonBytes, err := json.Marshal(developer)
if err != nil {
    panic(err)
}
fmt.Println(string(jsonBytes))

developer.ProjectRef.ID = "abc"

jsonBytes, err = json.Marshal(developer)
if err != nil {
    panic(err)
}
fmt.Println(string(jsonBytes))

Output (try it on the Go Playground):

{"name":"Charlie","project":null}
{"name":"Charlie","project":{"id":"abc"}}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading