Potrzebuję pomocy w Unmarshaling. Mam ten przykład kod:

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)
}

Co próbuję tutaj zrobić - Konwertuj bajty do struktury, gdzie typ jednego pola jest [] bajt . Błąd, który otrzymuję:

PANIC: JSON: Nie można unmarshal ciągnąć w polu struct OBJ.Data typu UINT8

Prawdopodobnie dlatego, że Parser widzi już, że pole "Dane" jest już plasterem i próbuje reprezentować "str1" jako niektórych char BYteCode (typ UINT8?).

Jak przechowywać całe dane wartość jako jedną tablicę bajtów? Ponieważ chcę wyrzucić wartość do kawałka ciągów później. Nie zawieram kawałka ciągów do struktury, ponieważ ten typ może się zmienić (tablica ciągów, int, ciąg itp.), Chciałbym to być uniwersalne.

go
0
Alexey 2 czerwiec 2018, 22:00

3 odpowiedzi

Najlepsza odpowiedź

Moim pierwszym zaleceniem będzie tylko użyć []string zamiast []byte Jeśli znasz typ wejścia, będzie to tablicą ciągów.

Jeśli data będzie tablicą JSON z różnymi typami, a więc najlepszą opcją jest użycie []interface{} zamiastu - Idź z radością unmarshal dla Ciebie JSON i możesz wykonać kontrole w czasie wykonywania, aby rzucić te bardziej szczegółowe zmienne wpisane na zasadzie potrzebne.

3
Venantius 2 czerwiec 2018, 20:50

Jeśli []byte naprawdę jest tym, czego chcesz, użyj json.RawMessage, który jest typu []byte, ale także wdraża metody dla JSON rozbiór gramatyczny zdania. Wierzę, że może to być to, czego chcesz, ponieważ zaakceptuje wszystko, co kończy się w data. Oczywiście musisz ręcznie analizować {x4}}, aby dowiedzieć się, co właściwie tam jest.

Jedną z możliwych bonusów jest to, że to pomija wszelkie silne parsowanie, ponieważ po prostu kopiuje byte s. Gdy chcesz użyć tych danych na coś, używasz []interface{}, a następnie użyj przełącznika typu, aby użyć pojedynczych wartości.

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)
        }

    }
}
3
RayfenWindspear 4 czerwiec 2018, 15:20

Twoje pytanie brzmi:

Konwertuj tablicę bajtów do struct z polem typu [] bajt

Ale nie masz BYTEARRAY, ale tablicy sznurki. Twoje pytanie nie jest takie samo jak twój przykład. Pozwól więc odpowiadać na twoje pytanie, możliwe są więcej rozwiązań w zależności od tego, jak daleko chcesz rozbiegać się z oryginalnych wymagań.

Jeden ciąg może być konwertowany na jeden bajtowy, dwa ciągi wymagają pierwszego przekształcenia do jednego ciągu. To jest problem. Drugim problemem są wsporniki kwadratowe w swoim sznurku JSON

Działa to dobrze, niejawnie konwertuje ciąg w łańcuchu JSON do bajtu:

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

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

fmt.Println(obj)
0
Bert Verhees 4 czerwiec 2018, 20:33