Как я могу узнать, является ли байт [] массивом или единственным объектом? - PullRequest
0 голосов
/ 22 октября 2019

Я создаю API, который будет получать объект по определенному маршруту. На этом маршруте я могу получить один объект или большую его часть.

Пример:

  [{"foo":"bar"}]
  {"foo":"bar"}

Как узнать, является ли запрос тела фрагментом или единственным объектом до того, как де json.Unmarshal. Более того, если это невозможно, каков наилучший способ принять эти два типа запросов тела и преобразовать их в список объектов?

Я ожидаю что-то вроде этого:

  type Foo struct {
    Foo string `json:"foo"`
  }

  func Bla() []Foo {

    fakeBody := []byte(`[{"foo":"bar"}]`)
    fakeBody2 := []byte(`{"foo":"bar"}`)     

    var foo []Foo

    // If fakeBody contains a array of objects
    // then parse it to the foo slice variable normally

    // So, if the fakeBody2 is a single object then 
    // parse this single object to the foo slice that will contain only
    // one element.

    return foo
  }

Ответы [ 3 ]

4 голосов
/ 22 октября 2019

Вот что я хотел бы сделать в этой ситуации, в следующем порядке:

  • Вы можете прочитать тело и проверить первый непробельный символ, чтобы увидеть, является ли он '[' или'{', и на основе этого выполнить демаршаллирование.
  • Вы можете сначала демаршировать как массив, а затем, если это не получится, как отдельный объект.
  • Вы можете демонтировать интерфейс {}, выполнитевведите утверждение и проанализируйте содержимое самостоятельно.
3 голосов
/ 22 октября 2019

Проверьте первый непробельный байт, чтобы определить, является ли документ JSON массивом или объектом. Декодировать соответственно.

func decode(body []byte) ([]Foo, error) {
    b = bytes.TrimLeft(body, " \t\n\r")
    if len(b) > 0 && b[0] == '[' {
        var v []Foo
        err := json.Unmarshal(body, &v)
        return v, err
    }
    var v [1]Foo
    err := json.Unmarshal(body, &v[0])
    return v[:], err
}
0 голосов
/ 23 октября 2019

Почему бы просто не добавить [ the и ], если это не их, а затем всегда обрабатывать его как массив?

body := []byte(`{"foo":"bar"}`)
body = bytes.TrimSpace(body)
if len(body) > 0 && body[0] != '[' {
    tmp := make([]byte, len(body)+2, len(body)+2)
    tmp[0] = '['
    tmp[len(tmp)-1] = ']'
    copy(tmp[1:len(tmp)-1], body)
    body = tmp
}

https://play.golang.org/p/YfnLgN9q64F

Или,сначала создайте массив, а затем на основе первого символа выполните маршал в массив или первый элемент:

f := make([]Foo, 1)
body := []byte(`{"foo":"bar"}`)
if len(body) > 0 && body[0] != '[' {
    json.Unmarshal(body, &f[0])
} else {
    json.Unmarshal(body, &f)
}
fmt.Println(f)

https://play.golang.org/p/1fxBKH3ZJyH

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...