Используйте разные клавиши json для сортировки и отмены сортировки - PullRequest
1 голос
/ 30 марта 2020

Что у меня есть: две структуры для какого-то API

type BaseUser struct {
    ID    int64  `json:"user_id"`
    Name  string `json:"user_name"`
    Email string `json:"user_email"`
}

и

type UserWithAddress struct {
    BaseUser
    Postal string `json:"user_postal"`
    City   string `json:"user_city"`
    Street string `json:"user_street"`
}

Что я хочу сделать: конвертирует json ключи из snake_case в camelCase. Допустим, это тело запроса

{
    "user_id": 123,
    "user_name": "test",
    "user_email": "test@mail.com",
    "user_postal": "12312",
    "user_city": "city",
    "user_street": "street"
}

Так что в результате, после какого-то преобразования, я бы хотел получить такой вывод

{
    "userId": 123,
    "userName": "test",
    "userEmail": "test@mail.com",
    "userPostal": "12312",
    "userCity": "city",
    "userStreet": "street"
}

Как сделать Сейчас я справляюсь с этим: Я сделал еще две структуры с тегом camelCase json

type BaseUserCamelCase struct {
    ID    int64  `json:"userId"`
    Name  string `json:"userName"`
    Email string `json:"userEmail"`
}

и

type UserWithAddressCamelCase struct {
    BaseUserCamelCase
    Postal string `json:"userPostal"`
    City   string `json:"userCity"`
    Street string `json:"userStreet"`
}

Мое преобразование выглядит как

var userWithAddressCamelCase UserWithAddressCamelCase

userWithAddressCamelCase.BaseUserCamelCase = BaseUserCamelCase(userWithAddress.BaseUser)
//I can't cast whole userWithAddressCamelCase object to another type because of different field names - BaseUser and BaseUserCamelCase
userWithAddressCamelCase.Name = userWithAddress.Name
userWithAddressCamelCase.Email = userWithAddress.Email
userWithAddressCamelCase.Postal = userWithAddress.Postal
//and so on

и мне это не нравится, потому что если BaseUser или UserWithAddress вырастет, я должен добавить соответствующее поле к %CamelCase структурам.

Мой вопрос: Есть ли другой, более эффективный способ обработки ключей?

Ответы [ 2 ]

3 голосов
/ 30 марта 2020

Есть ли еще один более эффективный способ обработки преобразования ключей?

Нет.

(Ну, исходя из вашего определения «эффективный». Вы можете использовать отражение , но я не буду рекомендовать это. Ваш код в порядке. Если какая-либо структура растет, вы добавляете несколько строк простого кода. Нет ничего плохого в простом коде, который не будет выдавать ошибки и будет быстрым во время выполнения. не выглядит необычно, это не значит, что здесь есть что "улучшить".)

1 голос
/ 30 марта 2020

Если вам больше всего нужно поддерживать список полей, то я бы предложил создать псевдонимы типов для ваших пользовательских типов и реализовать интерфейс json.Marshaler для тех псевдонимов, где вы бы реализовали пользовательский JSON. кодирование. Вы даже можете ввести альтернативный набор тегов и использовать их там.

Что-то вроде этого:

type BaseUser struct {
    ID    int64  `json:"user_id" jsonCC:"userId"`
    Name  string `json:"user_name" jsonCC:"userName"`
    Email string `json:"user_email" jsonCC:"userEmail"`
}

type BaseUserCamelCase BaseUser

func (bucc BaseUserCamelCase) MarshalJSON() ([]byte, error) {
    buccVal := reflect.ValueOf(bucc)
    kvpairs := []string{}

    for i := 0; i < buccVal.NumField(); i++ {
        k := buccVal.Type().Field(i).Tag.Get("jsonCC")
        v := buccVal.Field(i).Interface() //TODO: proper JSON encoding of things
        kvpairs = append(kvpairs, fmt.Sprintf("\"%s\":%#v", k, v))
    }

    return []byte(fmt.Sprintf("{%s}", strings.Join(kvpairs, ","))), nil
}

Затем вы можете выбрать стиль маршалинга:

user := BaseUser{
    ID:    123,
    Name:  "Johnny D03",
    Email: "j@example.com",
}

json.Marshal(user)
// {"user_id":123,"user_name":"Johnny D03","user_email":"j@example.com"}

json.Marshal(BaseUserCamelCase(user))
// {"userId":123,"userName":"Johnny D03","userEmail":"j@example.com"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...