Тип json.RawMessage
Тип json.RawMessage представляет собой сырые JSON-данные в виде байтового среза []byte. Он позволяет отложить парсинг JSON-данных, модифицировать их без потери структуры или проверять валидность. При использовании в структурах json.RawMessage не парсится автоматически, а сохраняется в исходном виде, что дает возможность обработать его позже или передать дальше.
Основное преимущество типа json.RawMessage заключается в том, что он позволяет частично декодировать JSON, оставляя некоторые поля в сыром виде для последующей обработки. Это особенно полезно при работе с динамическими или неизвестными структурами данных.
Синтаксис
type RawMessage []byte
Пример
Давайте рассмотрим использование json.RawMessage для отложенного парсинга JSON:
package 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)
}
Результат выполнения кода:
"ID: 1, Name: John"
"Raw data: {\"age\":30,\"city\":\"New York\"}"
"Parsed data: map[age:30 city:New York]"
Пример
Давайте рассмотрим пример модификации сырых JSON-данных перед маршалингом:
package 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))
}
Результат выполнения кода:
"{\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:
package 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))
}
}
Результат выполнения кода:
"Valid JSON payload: {\"data\":\"12345\"}"
"Invalid JSON payload: \"invalid json\""
Смотрите также
-
функцию
json.Unmarshal,
которая преобразует JSON-данные в структуры Go -
функцию
json.Marshal,
которая преобразует структуры Go в JSON-данные -
функцию
json.Valid,
которая проверяет валидность JSON-данных -
функцию
json.MarshalIndent,
которая преобразует данные в форматированный JSON