Можно ли демаршалировать json строку, представляющую массив байтов в структуре? - PullRequest
0 голосов
/ 04 августа 2020

У меня есть API, который возвращает объект JSON с полем, содержащим массив байтов (упрощенно):

{
    "value": "[208,188,149,77,179,245,29,184]"
}

Я могу демаршалировать string на []byte просто отлично:

var test = make([]byte,0)

testData := []byte("[208,188,149,77,179,245,29,184]")

_ = json.Unmarshal(testData, &test)

fmt.Println(len(test)) // output: 8

Однако, когда я пытаюсь демаршалировать это через struct, этого не происходит:

type Test struct {
    Value []byte `json:"value"`
}

testData := []byte(`
    {
        "value": "[208,188,149,77,179,245,29,184]"
    }
`)

var test = Test{}
err := json.Unmarshal(testData, &test)
if err != nil {
    t.Fatal(err) // output: illegal base64 data at input byte 0
}

Я получаю сообщение об ошибке:

illegal base64 data at input byte 0

Могу ли я что-нибудь сделать, кроме использования json.RawMessage и ручного демаршалинга этого поля отдельно?

Спасибо.

Ответы [ 2 ]

1 голос
/ 04 августа 2020

Причина, по которой это не работает, заключается в том, что Unmarshaller обнаруживает недопустимое значение в индексе 0, т.е. ". Таким образом, это будет работать, если ваша строка json имеет массив байтов без кавычек, потому что это правильный синтаксис.

    {
        "value": [208,188,149,77,179,245,29,184]
    }

Если у вас нет контроля над ответом, который вы получаете от api, вы можете сделать одно: напишите свой CustomMarshalJSON. Вы можете найти код здесь . Это сделает ваш код более чистым, и вам не придется беспокоиться о демаршалинге rawvalue каждый раз, когда вы получаете такое значение json.

0 голосов
/ 04 августа 2020

Как упоминалось в комментариях @icza и @DanielFarrell, это работает:

type Test struct {
    RawValue string `json:"value"`
    Value []byte `json:"-"`
}

testData := []byte(`
    {
        "value": "[208,188,149,77,179,245,29,184]"
    }
`)

var test = Test{}
err := json.Unmarshal(testData, &test)
if err != nil {
    t.Fatal(err)
}

value := make([]byte, 0)
err = json.Unmarshal([]byte(test.RawValue), &value)
if err != nil {
    t.Fatal(err)
}

// assign the value to the original struct
test.Value = value

fmt.Println(len(test.Value)) // output: 8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...