Home >Backend Development >Golang >How to Implement UnmarshalJSON for Derived Scalar Types in Go?

How to Implement UnmarshalJSON for Derived Scalar Types in Go?

Patricia Arquette
Patricia ArquetteOriginal
2024-11-26 18:41:16461browse

How to Implement UnmarshalJSON for Derived Scalar Types in Go?

UnmarshalJSON Implementation for Derived Scalars in Go

Problem:
A custom type that converts subtyped integer constants to strings and vice versa requires automatic unmarshalling of JSON strings. This is challenging because UnmarshalJSON does not provide a way to modify the scalar value without using a struct.

Solution:
To implement UnmarshalJSON for a derived scalar type, consider the following steps:

Use a Pointer Receiver:
Use a pointer receiver for the UnmarshalJSON method to modify the value of the receiver.

Unmarshal to a String:
Unmarshal the JSON text into a plain string, removing all JSON quoting.

Lookup and Set Value:
Use the Lookup function to retrieve the corresponding PersonID based on the string value. Assign the result to the receiver.

Example:

func (intValue *PersonID) UnmarshalJSON(data []byte) error {
  var s string
  if err := json.Unmarshal(data, &s); err != nil {
    return err
  }
  *intValue = Lookup(s)
  return nil
}

Code Example:

package main

import (
    "encoding/json"
    "fmt"
)

type PersonID int

const (
    Bob PersonID = iota
    Jane
    Ralph
    Nobody = -1
)

var nameMap = map[string]PersonID{
    "Bob":    Bob,
    "Jane":   Jane,
    "Ralph":  Ralph,
    "Nobody": Nobody,
}

var idMap = map[PersonID]string{
    Bob:    "Bob",
    Jane:   "Jane",
    Ralph:  "Ralph",
    Nobody: "Nobody",
}

func (intValue PersonID) Name() string {
    return idMap[intValue]
}

func Lookup(name string) PersonID {
    return nameMap[name]
}

func (intValue *PersonID) UnmarshalJSON(data []byte) error {
  var s string
  if err := json.Unmarshal(data, &s); err != nil {
    return err
  }
  *intValue = Lookup(s)
  return nil
}

type MyType struct {
    Person   PersonID `json: "person"`
    Count    int      `json: "count"`
    Greeting string   `json: "greeting"`
}

func main() {
    var m MyType
    if err := json.Unmarshal([]byte(`{"person": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {
        fmt.Println(err)
    } else {
        for i := 0; i < m.Count; i++ {
            fmt.Println(m.Greeting, m.Person.Name())
        }
    }
}

Output:

Hello Ralph
Hello Ralph
Hello Ralph
Hello Ralph

The above is the detailed content of How to Implement UnmarshalJSON for Derived Scalar Types in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
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