Странное поведение при Unmarshalling в struct в Go

Я разрабатываю инструмент, который можно реализовать, чтобы упростить процесс создания простых операций / конечных точек 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
", item)

fmt.Println(reflect.TypeOf(item))

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

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

Func, что unmarshalls пункт:

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 ответ


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

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

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

func main() {

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

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

Какие результаты:

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

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

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


Есть идеи?

10000