In this article, we will see how to unmarshal nested json data as a string/raw json data using Json.RawMessage.

There are several use cases of delaying the json decoding using the RawMessage.

  1. Caching the results can help you avoid repeatedly calling external services if you’re developing a web application that depends on external API services. Using json.RawMessage, you can store the unencoded JSON responses in a cache and decode them as required.
  2. In some cases, you may not know the structure of the JSON data beforehand. For example, you may be working with a dynamic data source that generates JSON data with different structures based on user input. In such scenarios, json.RawMessage can be used to decode the JSON data dynamically at runtime.
  3. This is also used while writing the mock tests. If you are writing tests for your JSON encoding or decoding functions, you can use json.RawMessage to test the raw JSON data instead of having to write mock objects or use hardcoded JSON strings.

json.RawMessage is mostly used for handling JSON data in Golang, especially in scenarios where the JSON structure may be unknown or dynamic.

Let us see an example:

Assume, we have the following json data where we don’t want to decode/unmarshal the Address field. Instead we need that data as the json string/raw json.

{
  "name": "John Doe",
  "age": 30,
  "address": {
    "street": "123 Main St",
    "city": "Anytown",
    "state": "CA"
  }
}

To unmarshal this JSON data, we can define the following struct:

type Person struct {
    Name    string          `json:"name"`
    Age     int             `json:"age"`
    Address json.RawMessage `json:"address"`
}

In the above example, we define the Address field to be of type json.RawMessage. This type is used to represent a raw JSON value.

This raw JSON value can be decoded later using the json.Unmarshal() function and for that we can define a separate struct Address that represents the structure of the Address field, like this:

type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
    State  string `json:"state"`
}
var person Person
err := json.Unmarshal(jsonData, &person)
if err != nil {
    fmt.Println("Error:", err)
}

var address Address
err = json.Unmarshal(person.Address, &address)
if err != nil {
    fmt.Println("Error:", err)
}

fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
fmt.Println("Address:", string(person.Address))

In the above example, we umarshalled the jsonData into person. Only the Name & age are unmarshaled whereas the Address field json data won’t be decoded instead stores it as a raw json data. This raw json data can be umarshaled later as per the use case and finally we are printing this rawJson data as a string.

Categorized in:

Tagged in: