Обновление API REST частичным json - PullRequest
0 голосов
/ 20 февраля 2019

Мы используем Golang для реализации REST API, который, в том числе CRUD, в службе обновления, клиент может отправлять частичный JSON, включая измененные поля, и нам необходимо обработать обновление сущности с этими изменениями.

Логически мынужно получить сущность по Id из БД в структуру, а затем демаршировать полезную нагрузку json в другую структуру и обновить сущность.

Однако, если полезная нагрузка json не полностью, например, у меня есть структура

type Customer struct {
    Id      int64 `json:"id"`
    Name    string `json:"name"`
    Age     int `json:"age"`
}

И запрос JSON выглядит следующим образом:

{
  "Name": "Updated name"
}

Затем клиент должен получить новое имя.

Это простой пример, на самом деле это может быть вложенная структура и вложенный JSON, как мы можем обработатьэтот случай с golang, или событие другого языка, как Java, .NET

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

из ваших комментариев кажется, что вы сталкиваетесь с проблемой нулевого значения, с которой сталкиваются многие пользователи с go, то есть как определить, соответствует ли входные данные допустимому значению - или это значение было обнулено из-за пропуска по умолчанию.

Единственный способ решить эту проблему - использовать указатели.Таким образом, в вашем примере измените структуру данных следующим образом:

type Customer struct {
    Id   *int64  `json:"id"`
    Name *string `json:"name"`
    Age  *int    `json:"age"`
}

Затем после демаршалирования все неинициализированные поля будут иметь значения nil, например,

var c Customer

err := json.Unmarshal(jsonData, &c)
if err != nil {
    panic(err)
}

if c.Id != nil {
    log.Println("TODO: added SQL update parms for c.Id:", *c.Id)
}
if c.Name != nil {
    log.Println("TODO: added SQL update params for c.Name:", *c.Name)
}
if c.Age != nil {
    log.Println("TODO: added SQL update parms for c.Age:", *c.Age)
}

Примечание: необходимо соблюдать осторожностьчтобы убедиться, что вы случайно не ссылаетесь на какие-либо нулевые указатели, которые могут вызвать мгновенный panic.

Работающий пример игровой площадки .

0 голосов
/ 20 февраля 2019

Если в запросе на обновление используется та же структура Customer, тогда поля структуры могут быть указателями, чтобы различать нулевое значение и значение, не заданное в JSON.
Теперь все, что вам нужно сделать, - это объединить существующую структуру в обновленную.Consumer struct.
Для этого вы можете использовать библиотеку https://github.com/imdario/mergo в Go.

package main

import (
    "fmt"
    "github.com/imdario/mergo"
    "encoding/json"
    "os"
)

type Address struct {
    City string `json:"city"`
}

type Customer struct {
    Id      int64 `json:"id"`
    Name    string `json:"name"`
    Age     int `json:"age"`
    Address *Address `json:"address"`
}


func main() {
    old1 := &Customer{Id:1, Name:"alpha", Age:5, Address:&Address{City:"Delhi"}}

    b := []byte(`{"name": "beta"}`) //no address, age specified picks from old
    up1 := new(Customer)
    json.Unmarshal(b, up1)
    if err := mergo.Merge(up1, old1); err != nil {
        fmt.Printf("err in 1st merge: %v\n", err)
        os.Exit(1)
    }
    m1, _ := json.Marshal(up1)
    fmt.Printf("merged to: %v\n", string(m1))

    old2 := &Customer{Id:1, Name:"alpha", Age:5, Address:&Address{City:"Delhi"}}
    b2 := []byte(`{ "address": {"city": "mumbai"}}`) //address specified
    up2 := new(Customer)
    json.Unmarshal(b2, up2)
    if err := mergo.Merge(up2, old2); err != nil {
        fmt.Printf("err in 1st merge: %v\n", err)
        os.Exit(1)
    }
    m2, _ := json.Marshal(up2)
    fmt.Printf("merged to: %v\n", string(m2))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...