Default value golang struct using `encoding/json` ?

You can set default value when you init your 'FileData'
See my example: https://play.golang.org/p/QXwDG7_mul
Page int has default value 33

package main

import (
    "encoding/json"
    "fmt"
)

type Response2 struct {
    Page   int      `json:"page"`
    Fruits []string `json:"fruits"`
}

func main() {
    str := `{"fruits": ["apple", "peach"]}`
    res := Response2{Page: 33 /*Default value*/}
    json.Unmarshal([]byte(str), &res)
    fmt.Println(res)
}

You can't because in Go types do not have constructors.

Instead, have either an explicit initializer function (or method on the pointer receiver) or a constructor/factory function (these are conventionally called New<TypeName> so yours would be NewFileData) which would return an initialized value of your type.

All-in-all, I have a feeling this looks like an XY problem. From your question, it appears you want to have a default value on one of your fields if nothing was unmarshaled. If so, just post-process the values of this type unmarshaled from JSON and if nothing was unmarshaled to Encodning set it to whatever default you want.

Alternatively you might consider this approach:

  1. Have a custom type for your field.

    Something like type EncodingMethod string should do.

  2. Have a custom JSON unmarshaling method for this type which would do whatever handling it wants.


Since your FileData isn't too complex, you can easily make use of json.Unmarshaler interface. Declare Encoding as a separate type and set the default value in the unmarshal method:

type FileData struct {
    UID string `json:"uid"`                 
    Size int `json:"size"`
    Content string `json:content`
    Encoding Encoding `json:encoding` // declared as a custom type
    User string `json:"user"`
}

type Encoding string

// implement the Unmarshaler interface on Encoding
func (e *Encoding) UnmarshalJSON(b []byte) error {
    var s string
    if err := json.Unmarshal(b, &s); err != nil {
        return err
    }
    if s == "" {
        *e = Encoding("base64")
    } else {
        *e = Encoding(s)
    }
    return nil
}

Now when you encode a json with empty Encoding value, it'll be set to base64:

var data1 = []byte(`{"uid": "UID", "size": 10, "content": "CONTENT", "encoding": "ASCII", "user": "qwe"}`)
var data2 = []byte(`{"uid": "UID", "size": 10, "content": "CONTENT", "encoding": "", "user": "qwe"}`)

func main() {
    fmt.Println("Hello, playground")
    f := FileData{}
    if e := json.Unmarshal(data1, &f); e != nil {
        fmt.Println("Error:", e)
    }
    fmt.Println(f, f.Encoding)
    if e := json.Unmarshal(data2, &f); e != nil {
        fmt.Println("Error:", e)
    }
    fmt.Println(f, f.Encoding)
}

Output:

{UID 10 CONTENT ASCII qwe} ASCII
{UID 10 CONTENT base64 qwe} base64

Working code: https://play.golang.org/p/y5_wBgHGJk

Tags:

Go