Тип json.RawMessage

Тип json.RawMessage представляет собой сырые JSON-данные в виде байтового среза []byte. Он позволяет отложить парсинг JSON-данных, модифицировать их без потери структуры или проверять валидность. При использовании в структурах json.RawMessage не парсится автоматически, а сохраняется в исходном виде, что дает возможность обработать его позже или передать дальше.

Основное преимущество типа json.RawMessage заключается в том, что он позволяет частично декодировать JSON, оставляя некоторые поля в сыром виде для последующей обработки. Это особенно полезно при работе с динамическими или неизвестными структурами данных.

Синтаксис

gotype RawMessage []byte

Пример

Давайте рассмотрим использование json.RawMessage для отложенного парсинга JSON:

gopackage main

import (
  "encoding/json"
  "fmt"
)

type User struct {
  ID   int       `json:"id"`
  Name string      `json:"name"`
  Data json.RawMessage `json:"data"`
}

func main() {
  jsonData := `{"id":1,"name":"John","data":{"age":30,"city":"New York"}}`

  var user User
  err := json.Unmarshal([]byte(jsonData), &user)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Printf("ID: %d, Name: %s\n", user.ID, user.Name)
  fmt.Printf("Raw data: %s\n", string(user.Data))

  var dataMap map[string]interface{}
  err = json.Unmarshal(user.Data, &dataMap)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Printf("Parsed data: %+v\n", dataMap)
}

Результат выполнения кода:

go"ID: 1, Name: John"
"Raw data: {\"age\":30,\"city\":\"New York\"}"
"Parsed data: map[age:30 city:New York]"

Пример

Давайте рассмотрим пример модификации сырых JSON-данных перед маршалингом:

gopackage main

import (
  "encoding/json"
  "fmt"
)

type Product struct {
  ID     int       `json:"id"`
  Name   string      `json:"name"`
  Metadata json.RawMessage `json:"metadata"`
}

func main() {
  initialData := `{"id":1,"name":"Laptop","metadata":{"color":"silver","weight":2.5}}`

  var product Product
  err := json.Unmarshal([]byte(initialData), &product)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  var metadata map[string]interface{}
  err = json.Unmarshal(product.Metadata, &metadata)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  metadata["price"] = 999.99
  metadata["inStock"] = true

  modifiedMetadata, err := json.Marshal(metadata)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  product.Metadata = modifiedMetadata

  result, err := json.MarshalIndent(product, "", "  ")
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Println(string(result))
}

Результат выполнения кода:

go"{\n  \"id\": 1,\n  \"name\": \"Laptop\",\n  \"metadata\": {\n  \"color\": \"silver\",\n  \"inStock\": true,\n  \"price\": 999.99,\n  \"weight\": 2.5\n  }\n}"

Пример

Давайте рассмотрим использование json.RawMessage для проверки валидности JSON:

gopackage main

import (
  "encoding/json"
  "fmt"
)

type Response struct {
  Status  string      `json:"status"`
  Payload json.RawMessage `json:"payload"`
}

func main() {
  validJSON := `{"status":"success","payload":{"data":"12345"}}`
  invalidJSON := `{"status":"error","payload":"invalid json"}`

  var response Response
  err := json.Unmarshal([]byte(validJSON), &response)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  if json.Valid(response.Payload) {
    fmt.Printf("Valid JSON payload: %s\n", string(response.Payload))
  } else {
    fmt.Println("Invalid JSON payload")
  }

  var response2 Response
  err = json.Unmarshal([]byte(invalidJSON), &response2)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  if json.Valid(response2.Payload) {
    fmt.Printf("Valid JSON payload: %s\n", string(response2.Payload))
  } else {
    fmt.Printf("Invalid JSON payload: %s\n", string(response2.Payload))
  }
}

Результат выполнения кода:

go"Valid JSON payload: {\"data\":\"12345\"}"
"Invalid JSON payload: \"invalid json\""

Смотрите также

  • функцию json.Unmarshal,
    которая преобразует JSON-данные в структуры Go
  • функцию json.Marshal,
    которая преобразует структуры Go в JSON-данные
  • функцию json.Valid,
    которая проверяет валидность JSON-данных
  • функцию json.MarshalIndent,
    которая преобразует данные в форматированный JSON