Home > Backend Development > Golang > How Can I Efficiently Unmarshal JSON Data into Specific Structs When Using Go's `json.Unmarshal` with `interface{}`?

How Can I Efficiently Unmarshal JSON Data into Specific Structs When Using Go's `json.Unmarshal` with `interface{}`?

Mary-Kate Olsen
Release: 2024-12-26 13:44:10
Original
380 people have browsed it

How Can I Efficiently Unmarshal JSON Data into Specific Structs When Using Go's `json.Unmarshal` with `interface{}`?

Unmarshaling into an Interface{} and Type Assertion

Problem Statement

When using Go's json.Unmarshal to decode strings from a message system, it is found that the result is a map[string]interface{} instead of the expected struct types (Somthing1 or Somthing2), making type assertion impossible.

Root Cause

The json.Unmarshal function, when unmarshaling into an interface{}, defaults to known types like []interface{} and map[string]interface{}. In the given code, the interface variable input receives a map[string]interface{} representing the unmarshaled JSON data, but the switch statement attempts to assert it as Somthing1 or Somthing2 directly.

Solution

Since the JSON is not natively unmarshaled into the desired structs, there are two options to address this issue:

1. Inspect and Convert from the Generic Map:

One approach is to inspect the map[string]interface{} and manually unpack the data into the appropriate struct types. However, this requires careful handling of potential errors and manual assignment of values.

2. Utilize a Custom JSON Unmarshaller:

A cleaner solution is to create a custom JSON unmarshaller to handle the unmarshaling process. This custom unmarshaller can discern the correct struct type based on the JSON data and unmarshal it accordingly. Here's an example of such an unmarshaller:

type Unpacker struct {
    Data       interface{}
}

func (u *Unpacker) UnmarshalJSON(b []byte) error {
    smth1 := &Something1{}
    err := json.Unmarshal(b, smth1)

    // no error, but we also need to make sure we unmarshaled something
    if err == nil && smth1.Thing != "" {
        u.Data = smth1
        return nil
    }

    // abort if we have an error other than the wrong type
    if _, ok := err.(*json.UnmarshalTypeError); err != nil && !ok {
        return err
    }

    smth2 := &Something2{}
    err = json.Unmarshal(b, smth2)
    if err != nil {
        return err
    }

    u.Data = smth2
    return nil
}
Copy after login

By passing an instance of this custom unmarshaller to json.Unmarshal, the resulting Data field will contain the unmarshaled data in the correct struct type, allowing for seamless type assertion.

The above is the detailed content of How Can I Efficiently Unmarshal JSON Data into Specific Structs When Using Go's `json.Unmarshal` with `interface{}`?. 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