#json #go #interface #unmarshalling #go-interface
# #json #Вперед #интерфейс #отмена сопоставления #go-интерфейс
Вопрос:
У меня есть интерфейс, который реализован несколькими структурами. В одном из моих методов я создаю экземпляр struct base для заданной строки, а затем анализирую json в определенную структуру. Для этого я реализовал UnmarshalJSON, но он никогда не вызывается.
Интерфейс:
type vehicle interface {
vehicleType() string
numberOfWheels() int
EngineType() string
}
Две структуры, реализующие интерфейс:
type truck struct {
loadCapacity int
capacityUnits string
}
func (t truck) vehicleType() string {
return "Truck"
}
func (t truck) numberOfWheels() int {
return 6
}
func (t truck) EngineType() string {
return "Gasoline"
}
func (t *truck) UnmarshalJSON(data []byte) error {
fmt.Println("Here in custom unmarshal")
return nil
}
// -------------------------------------------
type ev struct {
capacityInKWh int
}
func (e ev) vehicleType() string {
return "Electric Vehicle"
}
func (e ev) numberOfWheels() int {
return 4
}
func (e ev) EngineType() string {
return "Electric"
}
func (e ev) Capacity() int {
return e.capacityInKWh
}
Обратите внимание, что моя truck
структура также реализует пользовательский UnmarshalJSON.
Теперь, в основном, я пытаюсь сделать следующее:
func main() {
jsonData := []byte(`{"loadCapacity": 1000, "capacityUnits": "lb"}`)
vehicleType := "truck"
processVehicle(vehicleType, jsonData)
}
func processVehicle(vehicleType string, data []byte) {
var myVehicle vehicle
fmt.Println("Processing vehicle...")
switch vehicleType {
case "truck":
myVehicle = truck{}
}
err := json.Unmarshal(data, amp;myVehicle)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(myVehicle)
}
Но я получаю следующую ошибку:
json: невозможно преобразовать объект в исходное значение типа main.vehicle
Я знаю, что в реализованном for нет фактического тела UnmarshalJSON
truck
, но я бы ожидал, что хотя бы сообщение будет напечатано.
Что я делаю не так?
Комментарии:
1. Таким
truck
образом, реализуетсяjson.Unmarshaler
интерфейс, но вы разархивируете в typevehicle
, который является просто интерфейсом, так что это не работает. Вам нужно разобрать значение в конкретноеtruck
значение.2. @Flimzy но я не буду знать, какой тип транспортного
processVehicle
средства будет получен. Есть ли способ обойти это? Я имею в виду, я не хочу реализовывать несколькоswitch
повсюду3. Тогда все, что включает
vehicle
, должно принять решение о том, в какой тип разархивировать.4. Вам где -то нужен какой-то оператор switch (или эквивалентная логика). В Go нет волшебства.
5. В этом видео я рассказываю об использовании объекта контейнера для аналогичной ситуации, о которой @JimB, похоже, ускользнул.
Ответ №1:
Функция JSONUnmarshal находится в приемнике указателя. Используйте значение указателя для доступа к этому методу.
switch vehicleType {
case "truck":
myVehicle = amp;truck{} // <-- add amp; here
}
err := json.Unmarshal(data, myVehicle) // <-- amp; not needed here
Комментарии:
1. Это не связано с проблемой, связанной с вопросом.