РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
1140 of 1593 menu

Интерфейс json.Unmarshaler

Интерфейс json.Unmarshaler находится в пакете encoding/json и позволяет реализовать кастомную логику десериализации JSON-данных в пользовательский тип. Интерфейс содержит единственный метод UnmarshalJSON, который принимает срез байт (JSON-данные) и возвращает ошибку. Если ваш тип реализует этот интерфейс, то при вызове json.Unmarshal будет использоваться ваша реализация метода вместо стандартной.

Синтаксис

type Unmarshaler interface { UnmarshalJSON([]byte) error }

Для реализации интерфейса необходимо определить метод UnmarshalJSON с указанным синтаксисом. Метод получает исходные JSON-данные в виде байтового среза и должен заполнить поля структуры, используя собственную логику разбора.

Пример

Давайте реализуем кастомную десериализацию для структуры, которая хранит дату в строковом формате:

package main import ( "encoding/json" "fmt" "strings" ) type Person struct { Name string Age int City string } func (p *Person) UnmarshalJSON(data []byte) error { var raw map[string]interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } if name, ok := raw["name"].(string); ok { p.Name = strings.ToUpper(name) } if age, ok := raw["age"].(float64); ok { p.Age = int(age) } if city, ok := raw["city"].(string); ok { p.City = strings.ToUpper(city) } return nil } func main() { jsonData := []byte(`{"name":"alex","age":25,"city":"moscow"}`) var p Person err := json.Unmarshal(jsonData, &p) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Name: %s, Age: %d, City: %s\n", p.Name, p.Age, p.City) }

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

"Name: ALEX, Age: 25, City: MOSCOW"

В этом примере метод UnmarshalJSON преобразует все строковые поля структуры в верхний регистр в процессе десериализации. Обратите внимание, что метод должен быть определен на указателе на структуру.

Пример

Рассмотрим пример с обработкой нестандартного формата данных, где необходимо преобразовать строку в числовой тип:

package main import ( "encoding/json" "fmt" "strconv" ) type Product struct { ID string Price int } func (p *Product) UnmarshalJSON(data []byte) error { var raw map[string]interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } if id, ok := raw["id"].(string); ok { p.ID = id } if priceStr, ok := raw["price"].(string); ok { price, err := strconv.Atoi(priceStr) if err != nil { return err } p.Price = price } return nil } func main() { jsonData := []byte(`{"id":"p001","price":"1500"}`) var product Product err := json.Unmarshal(jsonData, &product) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("ID: %s, Price: %d\n", product.ID, product.Price) }

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

"ID: p001, Price: 1500"

В этом примере мы десериализуем JSON, где поле price передается как строка, но структура ожидает числовой тип. Метод UnmarshalJSON выполняет преобразование с помощью функции strconv.Atoi.

Пример

Рассмотрим обработку ошибок при десериализации с использованием интерфейса json.Unmarshaler:

package main import ( "encoding/json" "fmt" ) type User struct { Username string Email string } func (u *User) UnmarshalJSON(data []byte) error { var raw map[string]interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } username, ok := raw["username"].(string) if !ok || username == "" { return fmt.Errorf("username is required") } u.Username = username email, ok := raw["email"].(string) if !ok || email == "" { return fmt.Errorf("email is required") } u.Email = email return nil } func main() { jsonData := []byte(`{"username":"john","email":"john@example.com"}`) var user User err := json.Unmarshal(jsonData, &user) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Username: %s, Email: %s\n", user.Username, user.Email) }

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

"Username: john, Email: john@example.com"

В этом примере метод UnmarshalJSON проверяет наличие обязательных полей и возвращает ошибку, если данные некорректны. Это позволяет выполнять валидацию данных непосредственно в процессе десериализации.

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

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