sql.NullInt64 в JSON

Мне нужно сделать еще одно представление, которое содержит эти 2 представления?

Ответ: Нет

Нет ли другого способа такого как (без BigViewModel):

Да, вы можете использовать Tuple (придает магии возможность иметь несколько моделей).

Код:

 @model Tuple<LoginViewModel, RegisterViewModel>


    @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
    {
     @Html.TextBoxFor(tuple=> tuple.Item.Name)
     @Html.TextBoxFor(tuple=> tuple.Item.Email)
     @Html.PasswordFor(tuple=> tuple.Item.Password)
    }


    @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
     {
      @Html.TextBoxFor(tuple=> tuple.Item1.Email)
      @Html.PasswordFor(tuple=> tuple.Item1.Password)
     }
0
задан hendry 31 March 2019 в 02:06
поделиться

2 ответа

sql.NullInt64 существует, потому что SQL null нельзя представить как Go int. Это третье состояние, которое не может быть представлено ни одним значением int.

Одним из решений этой проблемы было бы представление таких значений SQL как *int, но для этого потребовалось бы выделение для случаев, когда значение не равно null в базе данных, и выделения плохо влияют на производительность.

Разработчики пакета SQL придумали решение NullInt64, которое кодирует третье состояние нуля в качестве дополнительного Valid логического значения. Это не хорошее решение, но лучшее, что мы можем получить.

Я не уверен, возможно ли написать маршаллер JSON для NullInt64, который бы работал так, как вы ожидаете.

По-прежнему существует проблема «третьего состояния» при сортировке в JSON. С ,omitempty было бы также опущено 0 int, так как вы можете отличить 0 от «не существует» / null?

В любом случае они не написали собственный маршаллер для NullInt64, поэтому он просто кодирует как структура, которая это есть.

Вы можете создать тип псевдонима для NullInt64, написать маршаллер JSON для кодирования того, как вы хотите, в JSON (вам нужен псевдоним, потому что вы не можете добавлять методы к типам из других пакетов). Вам также нужно будет разыграть между NullInt64 и sql.NullInt64.

0
ответ дан Krzysztof Kowalczyk 31 March 2019 в 02:06
поделиться

Вы можете использовать пользовательский тип для null int64. Этот тип работает так, как вы ожидали.

Пример использования:

package main

import (
    "encoding/json"
    "database/sql/driver" 
    "fmt"
    "strconv"
)

type user struct {
    ID   int             `db:"id"`
    Name string          `db:"name"`
    // pointer needed to omitempty work, otherwise output will be "age": null
    Age  *NullInt64 `db:"age" json:"age,omitempty"`
}

func main() {
    u := user{ID: 1, Name: "John"}
    j, _ := json.Marshal(u)
    fmt.Printf("%s\n", j)
}

//    Output:
//        {"ID":1,"Name":"John"}

type NullInt64 struct {
    Val     int64
    IsValid bool
}

func NewNullInt64(val interface{}) NullInt64 {
    ni := NullInt64{}
    ni.Set(val)
    return ni
}

func (ni *NullInt64) Scan(value interface{}) error {
    ni.Val, ni.IsValid = value.(int64)
    return nil
}

func (ni NullInt64) Value() (driver.Value, error) {
    if !ni.IsValid {
        return nil, nil
    }
    return ni.Val, nil
}

func (ni *NullInt64) Set(val interface{}) {
    ni.Val, ni.IsValid = val.(int64)
}

func (ni NullInt64) MarshalJSON() ([]byte, error) {
    if !ni.IsValid {
        return []byte(`null`), nil
    }

    return []byte(strconv.FormatInt(ni.Val, 10)), nil
}

func (ni *NullInt64) UnmarshalJSON(data []byte) error {
    if data == nil || string(data) == `null` {
        ni.IsValid = false
        return nil
    }

    val, err := strconv.ParseInt(string(data), 10, 64)
    if err != nil {
        ni.IsValid = false
        return err
    }

    ni.Val = val
    ni.IsValid = true

    return nil
}

func (ni NullInt64) String() string {
    if !ni.IsValid {
        return `<nil>`
    }

    return strconv.FormatInt(ni.Val, 10)
}
0
ответ дан Evgeny A. Mamonov 31 March 2019 в 02:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: