Golang, преобразовать байтовый массив в структуру с полем типа [] byte - PullRequest
0 голосов
/ 02 июня 2018

Мне нужна помощь с демаршалингом.У меня есть этот пример кода:

package main

import (
    "encoding/json"
    "fmt"
)

type Obj struct {
    Id   string `json:"id"`
    Data []byte `json:"data"`
}

func main() {
    byt := []byte(`{"id":"someID","data":["str1","str2"]}`)

    var obj Obj
    if err := json.Unmarshal(byt, &obj); err != nil {
        panic(err)
    }

    fmt.Println(obj)
}

Что я пытаюсь сделать здесь - преобразовать байты в структуру, где тип одного поля [] байт .Я получаю сообщение об ошибке:

panic: json: не удается распаковать строку в поле структуры Go Obj.data типа uint8

Это, вероятно, потому, что анализатор уже видит эти "данные"поле уже является слайсом и пытается представить "str1" как некоторый байт-код char (типа uint8?).

Как сохранить все значение data как один байтовый массив?Потому что я хочу позже разобрать значение для фрагмента строк.Я не включаю в строку ломтик строк, потому что этот тип может меняться (массив строк, int, string и т. Д.), Я хочу, чтобы это было универсальным.

Ответы [ 3 ]

0 голосов
/ 02 июня 2018

Если []byte действительно - это то, что вам нужно, используйте json.RawMessage, который равен типа []byte, но также реализует методы синтаксического анализа JSON.Я считаю, что это может быть то, что вы хотите, так как он примет все, что в конечном итоге в data.Конечно, вам нужно вручную разобрать Data, чтобы выяснить, что на самом деле там есть.

Один из возможных бонусов - это то, что это пропускает любой тяжелый анализ, потому что просто копирует byte s.Если вы хотите использовать эти данные для чего-то, вы используете []interface{}, а затем используйте переключатель типа для использования отдельных значений.

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

package main

import (
    "encoding/json"
    "fmt"
)

type Obj struct {
    Id   string          `json:"id"`
    Data json.RawMessage `json:"data"`
}

func main() {
    byt := []byte(`{"id":"someID","data":["str1","str2", 1337, {"my": "obj", "id": 42}]}`)

    var obj Obj
    if err := json.Unmarshal(byt, &obj); err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", obj)
    fmt.Printf("Data: %s\n", obj.Data)

    // use it
    var d []interface{}
    if err := json.Unmarshal(obj.Data, &d); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", d)

    for _, v := range d {
        // you need a type switch to deterine the type and be able to use most of these
        switch real := v.(type) {
        case string:
            fmt.Println("I'm a string!", real)
        case float64:
            fmt.Println("I'm a number!", real)
        default:
            fmt.Printf("Unaccounted for: %+v\n", v)
        }

    }
}
0 голосов
/ 02 июня 2018

Ваш вопрос:

преобразовать массив байтов в структуру с полем типа [] byte

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

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

Это прекрасно работает, неявно преобразует строку в json-строке в байтовый фрагмент:

byt := []byte(`{"id":"someID","data":"str1str2"}`)

var obj Obj
if err := json.Unmarshal(byt, &obj); err != nil {
    panic(err)
}

fmt.Println(obj)
0 голосов
/ 02 июня 2018

Моя первая рекомендация будет для вас просто использовать []string вместо []byte, если вы знаете, что тип ввода будет массивом строк.

Если data будет массивом JSON с различными типами, тогда лучше всего использовать вместо него []interface{} - Go с радостью разархивирует JSON для вас, и вы можете выполнять проверки во время выполнения для приведенияте в более конкретные типизированные переменные по мере необходимости.

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