Unmarshalling JSON с непечатными символами ASCII - PullRequest
0 голосов
/ 04 ноября 2018

Используя Go, как я могу разархивировать строку JSON, содержащую непечатаемые символы ASCII?

Например

testJsonString := "{\"test_one\" : \"123\x10456\x0B789\v123\a456\"}"
var dat map[string]interface{}
err := json.Unmarshal([]byte(testJsonString), &dat)
if err != nil {
    panic(err)
}

Урожайность:

panic: invalid character '\x10' in string literal

goroutine 1 [running]:
main.main()
    /tmp/sandbox903140350/main.go:14 +0x180

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

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

Аналогичным образом, еще одна проблема с данными, с которой я сталкиваюсь, - это удаление нескольких E escape-последовательностей, таких как \ 0 и \ a. Если я заменю строку, указанную выше, на эту строку, приведенную ниже, программа также завершится ошибкой. По существу это также терпит неудачу на любой escape-последовательности C https://en.wikipedia.org/wiki/Escape_sequences_in_C

testJsonString := "{\"test_one\" : \"123456789\\a123456\"}"

выдаст ошибку с

panic: invalid character 'a' in string escape code

goroutine 1 [running]:
main.main()
    /tmp/sandbox322770276/main.go:12 +0x100

Похоже, что он также не может быть демарширован, но не может быть экранирован путем проверки номера руны или проверки юникода (поскольку Go, по-видимому, обрабатывает его как обратную косую черту, за которой следует символ «a», которые оба являются юридическое)

Есть ли хороший способ справиться с этими крайними случаями?

1 Ответ

0 голосов
/ 04 ноября 2018

Согласно спецификации JSON https://jsonapi.org/format/ непечатаемые символы должны быть экранированы URI (или преобразованы в допустимые экранированные символы Юникода)

Итак, вот конвертер, который превращает непечатаемые символы в их экранированные формы. Затем они могут быть поданы в Unmarshal

Если это не совсем то поведение, которое вам нужно, то измените конвертер, чтобы удалить символы (с continue), или замените его на знак вопроса с руной или любым другим

Кстати, вторая проблема с \\a не "распечатывает как ожидалось" для меня. Пожалуйста, приведите лучший пример, который показывает проблему, с которой вы столкнулись

    package main

    import (
        "bytes"
        "encoding/json"
        "fmt"
        "unicode"
        "net/url"
    )

func safety(d string) []byte {
    var buffer bytes.Buffer
    for _, c := range d {
        s := string(c)
        if c == 92 { // 92 is a backslash
          continue
        }
        if unicode.IsPrint(c) {        
            buffer.WriteString(s)
        } else {
            buffer.WriteString(url.QueryEscape(s))
        }
        fmt.Println(buffer.String())
    }
    return buffer.Bytes()
}

func main() {
    testJsonString := "{\"test_one\" : \"123\x10456\x0B789\v123\a456\"}"
    var dat map[string]interface{}
    err := json.Unmarshal(safety(testJsonString), &dat)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%v", dat)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...