Home > front end >  Transform values when umarshaling
Transform values when umarshaling

Time:01-06

Given the code below, is it possible to transform first name while it's being unmarshaled? Say I want to always have it be lowercase whether it is in the actual json or not.

type Person struct {
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
}

func main() {
    jsonText := GetJsonFromSomewhere()
    var v Person
    json.Unmarshal(jsonText, &v)
}

CodePudding user response:

One way to do this is to create a custom type that implements the Unmarshaler interface from the encoding/json package. Here's a link to this interface. Any type which implements Unmarshaler can be used as the type of a struct field when doing JSON unmarshalling. When doing the unmarshalling, encoding/json will use your implementation of the interface's UnmarshalJSON function to convert the JSON bytes to the field type.

So you could write an UnmarshalJSON function which includes changing the string values to lowercase.

Here's an example of what that could look like:

type LowerCaseString string

func (l *LowerCaseString) UnmarshalJSON(bytes []byte) error {
    lowerCasedString := strings.ToLower(string(bytes))

    *l = LowerCaseString(lowerCasedString)

    return nil
}

Then, in your struct for JSON mapping, you can use your custom type instead of string:

type Person struct {
    FirstName LowerCaseString `json:"first_name"`
    LastName  LowerCaseString `json:"last_name"`
}

If you unmarshal into this struct, the values of FirstName and LastName will be lowercased (also note that you'll need to type convert them back to string to use them as strings).

testJSON := `{"first_name" : "TestFirstNAME", "last_name": "TestLastNAME"}`
var result Person

err := json.Unmarshal([]byte(testJSON), &result)
if err != nil { /*handle the error*/ }

fmt.Println(result.FirstName) // prints "testfirstname"

var stringLastName string
stringLastName = string(result.LastName) // need to type convert from LowerCaseString to string

fmt.Println(stringLastName) // prints "testlastname"

Here is the above code running in Go Playground.

  • Related