Странное поведение, когда Unmarshalling в struct в Go - PullRequest
0 голосов
/ 09 ноября 2018

Я разрабатываю инструмент, который можно реализовать, чтобы упростить процесс создания простых операций / конечных точек CRUD. Поскольку мои конечные точки не знают, какую структуру они будут получать, я создал интерфейс, который пользователи могут реализовать, и возвращает пустой объект для заполнения.

type ItemFactory interface {
    GenerateEmptyItem() interface{}
}

И пользователи будут реализовывать что-то вроде:

type Test struct {
    TestString string `json:"testString"`
    TestInt int `json:"testInt"`
    TestBool bool `json:"testBool"`
}

func (t Test) GenerateEmptyItem() interface{} {
    return Test{}
}

Когда объект Test создается, его типом является «Test», хотя func возвращает интерфейс {}. Однако, как только я пытаюсь разархивировать некоторые json того же формата в него, он удаляет его тип и становится типа "map [string] interface {}".

item := h.ItemFactory.GenerateEmptyItem()

//Prints "Test"
fmt.Printf("%T\n", item)

fmt.Println(reflect.TypeOf(item))

err := ConvertRequestBodyIntoObject(r, &item)
if err != nil {...}

//Prints "map[string]interface {}"
fmt.Printf("%T\n", item)

Функция, которая демаршализирует предмет:

func ConvertRequestBodyIntoObject(request *http.Request, object interface{}) error {
    body, err := ioutil.ReadAll(request.Body)
    if err != nil {
        return err
    }

    // Unmarshal body into request object
    err = json.Unmarshal(body, object)
    if err != nil {
        return err
    }

    return nil
}

Любые предложения относительно того, почему это происходит, или как я могу обойти это?

Спасибо

1 Ответ

0 голосов
/ 09 ноября 2018

В вашем вопросе отсутствует пример, демонстрирующий такое поведение, поэтому я просто предполагаю, что это именно то, что происходит.

func Generate() interface{} {
    return Test{}
}

func GeneratePointer() interface{} {
    return &Test{}
}

func main() {

    vi := Generate()
    json.Unmarshal([]byte(`{}`), &vi)
    fmt.Printf("Generate Type: %T\n", vi)

    vp := GeneratePointer()
    json.Unmarshal([]byte(`{}`), vp)
    fmt.Printf("GenerateP Type: %T\n", vp)
}

Какие выходы:

Generate Type: map[string]interface {}
GenerateP Type: *main.Test

Я предлагаю вам вернуть указатель в GenerateEmptyItem() вместо фактического значения структуры, продемонстрированного в примере GenerateP().

Пример игровой площадки

...